Python 解析文件

0 投票
3 回答
1440 浏览
提问于 2025-04-16 00:45

我想知道在以下情况下最好的处理方法是什么。

假设我们有一个很大的文件,这个文件记录了编译的输出,还有一些错误模式我想用来检查这个文件,比如错误模式可能是:

 - : error:
 - : error [A-Z]*[\d ]*
 - [A-Z]*[\d]* [E\e|rror:
 -  " Cannot open include file " 
 -  " Could not find " 
 - "is not a member of"
 - "has not been declared"

请告诉我这样做是否高效:

  • 把文件的内容放到一个变量里,然后关闭文件
  • 用grep命令查找列表中的每个错误
  • 或者为每个错误创建正则表达式,然后在变量中解析

谢谢!

3 个回答

0

这样做其实效率不高,因为你要把大量的数据都读到内存里,然后再进行操作。如果你的内存不够大,这样做可能就不太合适了。

不如用生成器来处理:

def parser(filename):
    with open(filename, 'r') as f: # For use in python > 2.4 I *think*.
        for line in f:
            if anymatches(line): # or whatever you want to do to generate a
                yield line       # true/false value

这样做的好处是不会把整个文件都加载到内存中,而且只会在你需要的时候才生成匹配的结果。所以如果你只想要前面 N 个匹配结果,可以这样做:

for i, match in zip(xrange(N), parser('mylogfile')):
    #do something with match
0

因为日志文件很大,所以检查错误的更有效的方法是逐行读取文件,检查每一行是否符合你的模式。你不想把一个巨大的文件不必要地放在内存里。

在Python中,可能可以这样做:

err = re.compile(': error(?::| [A-Z]*[\d ]*)|[A-Z]*\d* [Ee]rror:|' +
                 '" (?:Cannot open include file|Could not find) "|' +
                 '"(?:is not a member of|has not been declared)"')
with open('file.log') as f:
    for line in f:
        m = err.search(line)
        if m is not None:
            # this line indicates an error

不过你可能需要根据自己的需求调整正则表达式。另一种方法是准备一个静态字符串的列表,比如:

err_list = ['error', 'Cannot open include file', 'Could not find', 'is not a member of', 'has not been declared']

然后在每一行中搜索这些字符串:

with open('file.log') as f:
    for line in f:
        if any(line.find(e) for e in err_list):
            # this line indicates an error
2

如果日志文件很大,把它全部加载到内存里可能不是个好主意。相反,你可以先把所有的正则表达式预先编译好,然后逐行进行测试,比如:

def has_error(filename):
    with file(filename, 'r') as logfile:
        for line in logfile:
            for regexp in MY_REGEXPS:
                if regexp.search(line):
                    return True
        return False

撰写回答