我对Python相当陌生。我正在构建一个脚本来浏览一个日志文件,就像我在Perl中做了上百次一样。我使用的是哈希计算某些字段出现在日志文件中,就像我已经做了一百时间在Perl,一拉:Python re.sub考虑慢?
for $line in (<FILE>) {
($stuff1, $stuff2, $etc) = split(/\s+/, $line);
$stuff1 =~ s/something//;
$stuff2 =~ s/something//;
$count1{$stuff1}++;
$count2{$stuff2}++;
}
etc, print the hashes
我的Python是这样的:
import re
from collections import defaultdict
cntdaemon = defaultdict(int)
cntfaclevel = defaultdict(int)
cnthost = defaultdict(int)
redaemon1 = re.compile('\[[0-9]+\]')
redaemon2= re.compile(':')
refaclevel= re.compile(']')
with open("/var/adm/messages", 'r') as infile:
for line in infile:
(m, d, t, host, daemon, junk, idno, faclevel, text) = line.split(' ',8)
daemon = re.sub(redaemon1, '', daemon)
daemon = re.sub(redaemon2, '', daemon)
cntdaemon[daemon] += 1
faclevel = re.sub(refaclevel, '', faclevel)
cntfaclevel[faclevel] += 1
cnthost[host] += 1
print cntdaemon
print cntfaclevel
print cnthost
我发现这个版本比Perl版本慢20倍左右。我已经运行了预编译正则表达式的测试用例,并对其进行了“即时编译”,并且可以忽略不计,所以我知道Python不会浪费时间编译正则表达式。我怀疑是每次我做一个“re.sub”的时候,它会花费我所有的时间来销毁和编译字符串。
所以,简单的问题 - 有一个成语做替代更快?
我想我总是可以尝试写一个函数来做到这一点,而不分配....是一种方法往往采取?人们可以通过它的字符串转换成一个列表,然后ITER,C/C++字符串风格(当然,我只是那个扔在那里...)
这可能是重要的(也就是为什么我不在示例中使用Counter()) - 我需要在Python 2.6.4中编写它。如果这在2.7或3中会快得多,就这么说吧。但我没有选择。
1个字符的正则表达式可以通过'str.replace'或'str.translate(None,':')''加快速度。 – mgilson
实际上,跳过不必要的're.sub'调用应该可以使脚本速度提高三倍,更不用说可读性的好处了。但个人而言,如果它必须快速,我会在Awk中做这种事情,而不是Python。 –
有趣 - 我修剪系统日志外商投资企业后,我是从约4,000,000行读回至20000线和Python版本在大约相同的时间量Perl的版本上运行。所以: – wsanders