(Python) 解析文件以避免性能问题的最佳方法

4 投票
2 回答
796 浏览
提问于 2025-04-17 14:39

我对处理一个需要隔离信息的文件的最佳方法有些担心。

举个例子,想象一下一个日志文件,它的数据是分成多个块的,每个块里又有一些子块。

日志文件的例子:

data
data
data
data 
   block 1 start
    -sub block 1 start
    --data x
    --data y
    -sub block 1 end
    -sub block 2 start
    --data x
    --data marked as good
    --data z
    -sub block 2 end
    block 1 end
    block 1 summary

    block 2 start
    -sub block 1 start
    .....
    -sub block 1 end
    ....
data
data
data

我在寻找一种高效的方法来解析这个比较大的文件(里面有好几兆的文本),隔离出这些块,然后在每个块里检查特定的子块是否有某一行。如果这一行在子块里,我会保存这个块的开始和结束行,以及包含这一行的子块(但会丢弃那些没有数据的其他子块)。一直做到文件结束。

结果应该是这样的:

block 1 start
-sub block 2 start
--data marked as good
-sub block 2 end
block 1 summary
.....

目前我使用的方法是:我打开文件,然后把文件分成更小的部分来处理;我有三个列表来收集信息。

第一个列表叫做 List_general,它会包含整个日志文件解析的结果,去掉那些与我需要隔离的块无关的内容。基本上在这一步之后,我只会留下像上面例子中的块,去掉“数据”行。在这个过程中,我会检查“好数据”这个字符串,如果我至少看到一次这个字符串,就说明有我需要处理和保存的数据,否则我就结束这个函数。

如果有数据需要处理,我会逐行查看 List_general,开始隔离每个块和子块。从第一个块开始(也就是从块1的开始到块1的总结,如果你看例子的话)。

一旦我到达一个块的结束(块1总结);如果有标记为好的数据,我就会开始解析,逐个查看每个子块,找出哪个子块有好的数据。

我会逐行复制每个子块的内容,就像我处理块一样(基本上是从“子块1开始”到“子块1结束”逐行复制),并检查这个子块里是否有好的数据。如果有,我就把内容复制到最终列表中,否则我就删除这个列表,开始下一个子块。

我知道这种逐个解析每个部分的方法非常繁琐,而且资源消耗也很大;所以我在想有没有“更好”的方法来做到这一点。我对Python还很陌生,所以不太确定如何处理类似的问题。希望这里有人遇到过类似的问题,可以给我建议一下最佳的解决方案。

2 个回答

0

如果你能通过 block ... startblock ... end 来识别出区块或子区块的开始和结束,那么你就可以在阅读的过程中处理每个区块,并把结果存储到你需要的地方。

1

对于日志文件,我会在解析文件时丢掉那些我不关心的行,把有用的信息存储到sqlite里(可以看看sqlite3这个模块)。然后等我解析完文件后再进行报告和处理。

Sqlite可以设置为使用硬盘或内存来存储数据,所以你可以根据自己的需要来选择。

我喜欢这种方法,因为它很灵活,而且我不需要解析任何内容两次。

补充:这和这个类似吗?

class Parser:
    def __init__(self, logfile):
        self.log = open(logfile)
        self.logentry = []
    def next(self):
        found = False
        for line in self.log:
            self.logentry.append(line)            
            if <block ends>:
                e = '\n'.join(self.logentry)
                self.logentry = []
                yield e

撰写回答