Sorting by compare values in Python
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 condi开发者_JAVA百科tions: 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...
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.
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.
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"
精彩评论