Python:逐行有效地检查文件

时间:2015-07-15 20:43:41

标签: python performance file if-statement for-loop

我有非常大的文本文件(大约150万行或更多行)来解析一些信息。我每行都会检查某些关键字(我称之为" flags")。

但是,我为每一行运行了数十项检查,因此我的程序需要相当长的时间才能完成。有没有更快的方式来检查我目前的情况?以下只是我正在做的一个例子:

nameFound = false
ageFound = false

for line in file:
    if not nameFound and line.find('name:') != -1:
        do something
    elif not ageFound and line.find('age:') != -1:
        do something
    elif line.find('test pass') != -1:
        do something
    elif line.find('test fail') != -1:
        do something
    and so on ...

一些"标志"只出现一次(虽然我不知道文件中的位置或顺序),所以我使用"找到"变量用于短路检查那些"标志"。其他信息出现了数千次,所以我不能使用"发现"在我的条件下变量。 我知道的一件事是每一行,如果它包含一个"标志",最多只有一个标志。考虑到这些信息,是否有更有效的方法走吧?

4 个答案:

答案 0 :(得分:2)

只是一个建议:您可以使用"标记"的列表,并迭代它们。

flags = [('name:', nameMethod), ('age:', ageMethod), ('test pass', tpMethod), ('test fail', tfMethod), ... ] #methods are functions without ()

for line in lines:
  for flag, func in flags:
    if line.find(flag) != -1:
      func(args) #your args
      break #same functionality as elif

顺便说一句,使用in运算符优于str.findstr.index。所以if flag in line: #do something

这只是为了提高可读性。你绝对应该进行分析以找出瓶颈,然后看看应该/不应该修复什么。我确定使用in代替str.find效率更高(我的测试估算值约为3倍)。

答案 1 :(得分:2)

在Python中,你无法做很多事情来加快速度。你一行一行,只读一次文件。你已经做了足够的事情来挤压"短路时更快地摆脱循环。代码运行所需的时间与文件大小成正比。

首先使用更快的工具过滤文件的行可能会更好。例如,mine Unix命令通常在C中实现,并且速度非常快(比在Python中实现循环要快得多)。因此,您可以使用这样的命令(在Linux或Unix上)过滤行,然后在过滤后的文件上运行程序:

categories

另一种选择可能是使用Cython来尝试通过将代码编译为C来加速代码。但实际上,这不会让你 获得更多。

答案 2 :(得分:0)

考虑一下:每个if整个行中搜索(可能不存在的)标记。

假设你的线路是“爸爸已到达机场”,而你的旗帜列表是[' M','妈妈']那么很明显如果找不到M,妈妈也不会被发现。

如果您愿意付出努力来实施它们,Aho-CorasickRabin-Karp算法将提供显着的加速。

答案 3 :(得分:0)

正则表达式搜索可能更快:

import re
flags = "name|age|etc"

for line in file:
    m = re.match(flags, line)
    if m.group():
        do_something(m)

或者,您可以将所有测试放在while循环中,以便在找到标志后立即退出:

flags = ['name', 'age', 'foo']

for line in file:
    i = 0
    while i < len(flags):
        if (line.find(flags[i])):
            do_something(flags[i])
            i = len(flag[i]) 
        i += 1

如果您需要为每个标志执行不同的操作,可以将该逻辑放在方法中。