python加速这个正则表达式子

时间:2014-05-09 21:38:05

标签: python regex

p = re.compile('>.*\n')
p.sub('', text)

我想删除所有以'>'开头的行。我有一个非常大的文件(3GB),我处理大小为250MB的块,所以变量" text"是一个250MB的字符串。 (我尝试了不同的大小,但整个文件的性能总是相同的。)

现在,我可以以某种方式加速这个正则表达式吗?我尝试了多行匹配,但速度慢了很多。还是有更好的方法?

(我已经尝试拆分字符串然后过滤掉这样的行,但它也慢了(我也试过一个lambda而不是def del_line :(可能不是工作代码,它只是#)来自记忆):

def del_line(x): return x[0] != '>'

def func():
    ....
    text = file.readlines(chunksize)
    text = filter(del_line, text)
    ... 

编辑: 正如评论中所建议的那样,我也尝试逐行行走:

text = []
for line in file:
    if line[0] != '>':
        text.append(line)
text = ''.join(text)

那也慢了,需要~12秒。我的正则表达需要~7秒。 (是的,那很快,但它也必须在较慢的机器上运行)

编辑:当然,我也试过str.startswith('>'),它的速度较慢......

2 个答案:

答案 0 :(得分:1)

如果有机会,将grep作为子流程运行可能是最实用的选择。

如果由于某种原因你不能依赖grep,你可以尝试实施一些"技巧"使grep快。作者自己可以在这里阅读:http://lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html

在文章的最后,作者总结了要点。对我来说最突出的是:

  

此外,GNU grep AVOIDS突破了输入线。寻找   换行会使grep减慢几倍,因为   找到它必须查看每个字节的新行!

这个想法是将整个文件加载到内存中,并在字节级而不是行级上迭代它。只有当您找到匹配项时,才会查找行边界并将其删除。

你说你必须在其他计算机上运行它。如果它已经触及你并且你还没有这样做,可以考虑在PyPy而不是CPython(默认解释器)上运行它。这可能(或可能不)通过一个重要因素来改善运行时间,具体取决于程序的性质。

另外,正如一些评论已经提到的那样,与实际的grep基准测试,以获得合理的速度基线。如果你在Windows上,可以在Cygwin上获取它,这很容易。

答案 1 :(得分:0)

这不是更快吗?

def cleanup(chunk):
    return '\n'.join(st for st in chunk.split('\n') if not(st and st[0] == '>'))
编辑:是的,那不是更快。这是两倍慢。

根据Ryan P.的建议,也许可以考虑使用子进程和像grep这样的工具。你甚至可以利用多处理。