Pythonic和有效的方法来定义多个正则表达式,以便在多次迭代中使用

时间:2012-03-28 19:43:48

标签: python regex performance

我目前正在编写一个Python脚本来处理大约10,000个输入文档。基于脚本的进度输出,我注意到前400个文档的处理速度非常快,然后脚本速度变慢,尽管输入文档的大小大致相同。

我假设这可能与大多数文档处理都是使用正则表达式完成这一事实有关,这些正则表达式在编译后我不会保存为正则表达式对象。相反,我会在需要时重新编译正则表达式。

由于我的脚本有大约10个不同的函数,所有函数都使用了大约10 - 20个不同的正则表达式模式,我想知道在Python中有什么更有效的方法可以避免一遍又一遍地重新编译正则表达式模式(在Perl I中)可以简单地包含一个修饰符//o)。

我的假设是,如果我使用

将正则表达式对象存储在各个函数中
pattern = re.compile()

在下次迭代函数的下一次调用(每个函数被调用但每个文档一次)之前,不会保留生成的正则表达式对象。

创建预编译的正则表达式的全局列表似乎是一个没有吸引力的选项,因为我需要将代码列表存储在我的代码中的不同位置而不是它们实际使用的位置。

关于如何整齐有效地处理这个问题的任何建议?

4 个答案:

答案 0 :(得分:10)

re模块缓存已编译的正则表达式模式。当缓存达到re._MAXCACHE的大小时,缓存被清除,默认值为100.(由于你有10个函数,每个函数有10-20个正则表达式(即100-200个正则表达式),所以观察到的减速是有意义的清除缓存。)

如果您可以更改私有变量,那么对您的程序进行快速而又脏的修复可能是将re._MAXCACHE设置为更高的值:

import re
re._MAXCACHE = 1000

答案 1 :(得分:5)

上次我查看时,re.compile维护了一个相当小的缓存,当它填满时,只是清空它。 DIY没有限制:

class MyRECache(object):
    def __init__(self):
        self.cache = {}
    def compile(self, regex_string):
        if regex_string not in self.cache:
            self.cache[regex_string] = re.compile(regex_string)
        return self.cache[regex_string]

答案 2 :(得分:2)

编译的正则表达式由re.compilere.searchre.match自动缓存,但Python 2.7中的最大缓存大小为100,因此您将溢出缓存。< / p>

  

创建预编译的正则表达式的全局列表似乎是一个没有吸引力的选项,因为我需要将代码列表存储在我的代码中的不同位置而不是它们实际使用的位置。

您可以在使用它们的地方附近定义它们:就在使用它们的函数之前。如果你在不同的地方重复使用相同的RE,那么最好全局定义它以避免在多个地方修改它。

答案 3 :(得分:1)

本着“简单就是更好”的精神,我会使用像这样的小辅助功能:

def rc(pattern, flags=0):
    key = pattern, flags
    if key not in rc.cache:
        rc.cache[key] = re.compile(pattern, flags)
    return rc.cache[key]

rc.cache = {}

用法:

rc('[a-z]').sub...
rc('[a-z]').findall <- no compilation here

我还建议您尝试regex。除了库存的许多其他优点之外,其MAXCACHE默认为500,并且在溢出时不会完全掉线。