2

Newbie in Python need help!

I have a file with a structure:

[timestamp] [level] [source] message

which contains following lines(for example):

[Wed Oct 11 14:34:52 2000] [error] [client 127.0.0.1] error message
[Wed Oct 11 18:56:52 2000] [warning] [client 127.0.0.1] error message
[Wed Oct 11 22:15:52 2000] [critical] [client 127.0.0.1] error message

And i need to sort this lines by [level] and display a result in STDOUT. But there is two conditions: we must have opportunity to select [level] name which uses to sorting and all lines with upper [level] should be displayed too.

[level] values:
critical = 50
error = 40
warning = 30
info = 20
debug = 10

I decide to do this with suits:

suits = {'critical': 50, 'error': 40, 'warning': 30}
l = ['critical','error','warning']
print sorted(l, key=suits.get)

But i suppose it's not the best way.

I hope you'll help me to solve this...

2
  • 1
    What did you try? Where did you get stuck? We won't write your program for you, but if you update your question with the code you're working on and explain what your exact problem is, we will be glad to help. Commented Jul 11, 2011 at 20:01
  • I don't ask for writing a code. I just wanna know what path is better to do that. Commented Jul 11, 2011 at 20:05

3 Answers 3

4

I would divide this into two parts:

1) Write a function that, given a line of the file, returns the level number. Call this level_number for part 2.

2) Use that function with the key parameter in your chosen sort call:

with open(fname) as f:
  sorted_lines = sorted(f, key=level_number)

The function for 1) can be created with split or a regular expression.

Sign up to request clarification or add additional context in comments.

2 Comments

I'd adjust "part one" to return a tuple containing the level number and the timestamp (or the line itself). That way we'd get secondary sorting for items with identical levels.
I'll try to coded this task according to your model. Thank you.
2

Here is working code (I couldn't help, even though @Hamidi said "We won't write your program for you" ;)

import re

PAT = re.compile(r'\[(?P<time>[^\]]+)\] \[(?P<level>[^\]]+)\] \[(?P<client>[^\]]+)\] (?P<message>\S+)')
LEVELS = ['critical', 'error', 'warning', 'info', 'debug']

def level_number(line):
    match = PAT.match(line)
    if match:
        level = PAT.match(line).groupdict()['level']
        return LEVELS.index(level)
    return len(LEVELS)

with open('log.txt') as f:
    result = sorted(f, key=level_number)

Note, I included the regex with groups for each part (this may come in convenience for further processing). HTH.

4 Comments

Unexpected solution. So, now i need to understand your code and everything will be fine :)
@alienhard, +1 for the effort, and in the future I'll say probably won't write your program for you, I promise ;)
I'm not sure it would work with levels in uppercase, have you tried it?
@Apollo46 @F.C. This won't match upper- or mixed case level strings. But you can just convert level to lowercase with level.lower(). (Note, if a level is not recognized you'll get a ValueError. You may want to catch it to make the code more robust).
2

Quick one-liner to give you some idea to get the key from the text line:

{'critical': 50, 'error': 40, 'warning': 30, 'info': 20, 'debug': 10}.get(line.split('] [')[1].lower(), 0)

Do not use this in production code, remember, "readability counts"

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.