从文本日志文件生成日志事件对象
我有一个文本日志文件,内容大概是这样的:
Line 1 - Date/User Information Line 2 - Type of LogEvent Line 3-X, variable number of lines with additional information, could be 1, could be hundreds
然后这个序列会重复。
这个日志大约有2万行,包含50多种日志事件,大概有1.5万条不同的用户/日期事件。我想用Python来解析这些信息,并让它们可以被查询。
所以我想创建一个叫做LogEvent的类,记录用户、日期(我会提取并转换成日期时间格式)、动作、描述……大概是这样的:
class LogEvent(): def __init__(self,date,user): self.date = date # string converted to datetime object self.user = user self.content = ""
每当解析到一行包含用户/日期信息的文本时,就会创建这样的事件。
为了添加日志事件的信息和任何描述内容,可以有类似这样的东西:
def classify(self,logevent): self.logevent = logevent def addContent(self,lineoftext): self.content += lineoftext
处理文本文件时,我会使用readline()方法,一次处理一行。如果这一行是用户/日期信息,我就创建一个新对象并把它加到一个列表里……
newevent = LogEvent(date,user) eventlist.append(newevent)
然后开始添加动作/内容,直到遇到一个新对象。
eventlist[-1].classify(logevent) eventlist[-1].addContent(line)
这些步骤听起来都很合理(除非你能说服我有更聪明的方法或者我不知道的有用的Python模块)。我在考虑如何最好地分类日志事件类型,因为我有一个固定的日志事件类型列表,可能会有超过50种类型,而我不想直接把整行文本当作日志事件类型。相反,我需要把这一行的开头和可能的值列表进行比较……
我不想这样做,创建50个这样的东西:
if line.startswith("ABC"): logevent = "foo" if line.startswith("XYZ"): logevent = "boo"
我考虑过使用字典作为查找表,但不太确定如何用“startswith”来实现……如果有建议的话,我会很感激,对不起如果我说得太啰嗦了。
2 个回答
因为我之前提问的方式不太好,所以我想了想,得出了这个答案,跟这个讨论有点相似。
我想要一个干净、容易管理的办法,来根据特定条件不同地处理每一行文本。我不想用一堆if/else语句。所以我尝试把条件和结果(处理方式)放到一个叫decisionDict的字典里。
### RESPONSES WHEN CERTAIN CONDITIONS ARE MET - simple examples def shorten(line): return line[:25] def abc_replace(line): return line.replace("xyz","abc") ### CONDITIONAL CHECKS FOR CONTENTS OF LINES OF TEXT - simple examples def check_if_string_in_line(line): response = False if "xyz" in line: response = True return response def check_if_longer_than25(line): response = False if len(line)>25: response = True return response ### DECISION DICTIONARY - could be extended for any number of condition/response decisionDict = {check_if_string_in_line:abc_replace, check_if_longer_than25:shorten} ### EXAMPLE LINES OF SILLY TEXT lines = ["Alert level raised to xyz", "user 5 just uploaded duplicate file", "there is confusion between xyz and abc"] for line in lines: for k in decisionDict.keys(): if k(line):#in line: print decisionDict[k](line)
这样做可以把所有的条件和动作整齐地分开。而且目前这种方法不允许对同一行文本应用多个条件。一旦找到第一个条件为'True'(真的),就会继续处理下一行文本。
如果你有一个字典,里面的键是你的日志事件类型,而值是你想放进 logevent
属性的内容,你可以这样做,
logEvents = {"ABC":"foo", "XYZ":"boo", "Data Load":"DLtag"}
假设你从日志文件中得到的这一行是,
line = "Data Load: 127 row uploaded"
你可以检查这一行的开头是否有上面字典中的任何一个键,
for k in logEvents:
if line.startswith(k):
logevent = logEvents[k]
这段代码会遍历 logEvents
中的所有键,检查 line
是否以其中一个键开头。你可以在 if 条件成立后做任何你想做的事情。你也可以把这段代码放进一个函数里,这个函数可以在解析完一行包含用户或日期信息的文本后被调用。如果你想在没有找到任何键的情况下做点什么,可以这样做,
for k in logEvents:
if line.startswith(k):
logevent = logEvents[k]
return
raise ValueError( "logEvent not recognized.\n line = " + line )
需要注意的是,你抛出的具体异常类型并不是特别重要。我选择了一个内置的异常,以避免创建子类。在这里你可以看到所有内置的异常。