为什么搜索>;100个不同的正则表达式会让我的python脚本慢到爬行速度吗?

为什么搜索>;100个不同的正则表达式会让我的python脚本慢到爬行速度吗?,python,regex,performance,Python,Regex,Performance,我见过一些关于Python不接受超过100个组的正则表达式的线程。我有一个类似但(我想?)不同的问题 我编写了一个python脚本,用于在大型(10-100MB)复杂日志文件中查找“有趣”的内容。我有一个字符串列表,其中每个字符串在调用re.search时用作正则表达式。在日志记录的每一行上逐个运行每个正则表达式。当我的列表包含100个或更少的正则表达式字符串时,所有内容都会运行良好。但是,当我向列表中再添加一个脚本时,脚本运行得太慢,以至于没有任何用处 我写了一个简短的脚本来模拟这个问题。有人

我见过一些关于Python不接受超过100个组的正则表达式的线程。我有一个类似但(我想?)不同的问题

我编写了一个python脚本,用于在大型(10-100MB)复杂日志文件中查找“有趣”的内容。我有一个字符串列表,其中每个字符串在调用re.search时用作正则表达式。在日志记录的每一行上逐个运行每个正则表达式。当我的列表包含100个或更少的正则表达式字符串时,所有内容都会运行良好。但是,当我向列表中再添加一个脚本时,脚本运行得太慢,以至于没有任何用处

我写了一个简短的脚本来模拟这个问题。有人能帮我确定为什么会发生这种情况,并就我能做些什么提供一些建议吗

下面是脚本的一些示例输出。我运行脚本的日志很少少于250000行,通常为100-200万行

$ ./regexTest.py 100 10000
Running regex search
Done regex search
Time Elapsed: 0.734515 seconds

$ ./regexTest.py 101 10000
Running regex search
Done regex search
Time Elapsed: 44.428968 seconds
谢谢大家抽出时间


#/usr/bin/python
#------------------------------------------------------------------------------
#文件:regexTest.py
#描述:模拟尝试使用多个列表的问题
#100个正则表达式字符串使脚本变得无用
#例如:
#./regexTest.py 100 10000
#./regexTest.py 101 10000
#------------------------------------------------------------------------------
从随机导入randint
进口稀土
导入系统
导入时间
def main():
如果(len(sys.argv)!=3):
打印“用法:%s”%sys.argv[0]
系统出口(1)
numRegexes=int(sys.argv[1])
logFileLength=int(sys.argv[2])
正则表达式=[]
#生成由5到20个元素组成的随机正则表达式
#小写字母
对于范围内的i(numRegexes):
randomLetters=[chr(randint(97120))表示范围内的x(randint(5,20))]
baseRegex=“”.join(随机字母)
regex=baseRegex+str(i)
regexes.append(regex)
#模拟日志文件的内容
数据=[]
对于范围内的i(logFileLength):
randomLetters=[chr(randint(97120))表示范围内的x(randint(20100))]
logLine=“.join(随机字母)
data.append(日志行)
打印“运行正则表达式搜索”
startTime=time.time()
对于行输入数据:
对于正则表达式中的正则表达式:
ret=重新搜索(正则表达式,行)
如果(ret不是无):
打印“找到正则表达式”
打印“完成正则表达式搜索”
endTime=time.time()
打印“已用时间:%f秒”%(结束时间-开始时间)
如果(\uuuuu name\uuuuuu==“\uuuuuu main\uuuuuu”):
main()

您使用的正则表达式错误;你应该编译它们。
re
模块中有一个缓存,用于不编译正则表达式的懒人;缓存的大小在Python2.7上为100,在Python3.4上为512。缓存的大小可在
re.\u MAXCACHE
上找到。在耗尽这100个条目后,所有编译的模式都将从缓存中排出。如果您看到您的程序使用的不仅仅是
re.\u MAXCACHE
regex,您应该使用
re.compile
预编译它们

regexes = [ re.compile(i) for i in regexes ]
for line in data:
    for regex in regexes:
        ret = regex.search(line)
        if ret is not None:
            print("Regex found")
此外,如果您真的没有使用这些匹配项中的任何一个,您应该将它们组合成一个。因此,您可以尝试使用“|”条形运算符将它们连接起来,使它们相互替代:

megaregex = re.compile('|'.join(regexes))
for line in data:
    ret = megaregex.search(line)
    if ret is not None:
        print("Regex found")

您正在破坏正则表达式缓存。我的脚本的本质是,每个正则表达式将一个复杂的日志消息映射为人类可读的内容。因此,每个正则表达式都与一个字符串相关联。否则,我会尝试将它们全部“或”在一起。谢谢你提出的编辑它们的想法。我不知道有缓存限制,所以我从不理解为什么有人会编译正则表达式,因为它增加了额外的看似不必要的工作。
megaregex = re.compile('|'.join(regexes))
for line in data:
    ret = megaregex.search(line)
    if ret is not None:
        print("Regex found")