【问题标题】:Replace Multiple Strings in a Large Text File in Python在 Python 中替换大型文本文件中的多个字符串
【发布时间】:2017-05-02 18:07:07
【问题描述】:

问题:

替换大型文本文件中的多个字符串模式需要很长时间。 (Python)

场景:

我有一个没有特定结构的大文本文件。但是,它包含几种模式。例如,电子邮件地址和电话号码。

文本文件有 100 多种不同的此类模式,文件大小为 10mb(大小可能会增加)。文本文件可能包含也可能不包含所有 100 种模式。

目前,我正在使用re.sub() 替换匹配项,执行替换的方法如下所示。

readfile = gzip.open(path, 'r') # read the zipped file
lines = readfile.readlines() # load the lines 

for line in lines:
    if len(line.strip()) != 0: # strip the empty lines
        linestr += line

for pattern in patterns: # patterns contains all regex and respective replaces
    regex = pattern[0]
    replace = pattern[1]
    compiled_regex = compile_regex(regex)
    linestr = re.sub(compiled_regex, replace, linestr)

这种方法需要大量时间来处理大文件。有没有更好的优化方法?

我正在考虑将+= 替换为.join(),但不确定会有多大帮助。

【问题讨论】:

  • 你有正则表达式模式或简单的字符串吗?
  • 如果你有这么大的文件,你也可以用主键对数据进行一次排序,然后简单地进行二进制搜索,这将大大提高性能。这是一次性的权衡,对我来说似乎是一个快速的胜利。此外,在这种规模下,应该考虑使用数据库。如果您正在处理大量数据,则对其应用结构几乎总是会产生很大的改进。因此,大学经常将数据结构作为一门课程教授。
  • @Krazor:问题作者说文件没有结构。所以我想知道你是如何考虑排序的?
  • 那么对不起。正如@salah 所述,您绝对应该考虑使用生成器!

标签: python regex algorithm optimization time-complexity


【解决方案1】:

您可以使用lineprofiler 来查找代码中哪些行花费的时间最多

pip install line_profiler    
kernprof -l run.py

另外,我认为你在内存中构建的字符串太大,也许你可以使用generators

【讨论】:

  • 在这种情况下使用生成器是有意义的。我不明白 lineprofiler 有什么帮助?
  • @salah 谢谢,我对生成器不是特别了解。我会调查的。那么,在您看来,将文本文件分成块并执行正则表达式替换可能会更优化?
  • 我不完全确定它是否会更快,但它肯定会更有效。
【解决方案2】:

您可能会获得更好的结果:

large_list = []

with gzip.open(path, 'r') as fp:
    for line in fp.readlines():
        if line.strip():
            large_list.append(line)

merged_lines = ''.join(large_list)

for regex, replace in patterns:
    compiled_regex = compile_regex(regex)
    merged_lines = re.sub(compiled_regex, replace, merged_lines)

但是,了解您应用的处理类型可以实现进一步优化。事实上,最后一行将占用所有 CPU 功率(和内存分配)。如果可以逐行应用正则表达式,则可以使用 multiprocessing 包获得很好的结果。由于 GIL (https://wiki.python.org/moin/GlobalInterpreterLock),线程不会给你任何东西

【讨论】:

  • 我赞同你对多处理的看法。而且,我的方案涉及逐行和跨行(固定结构)应用正则表达式。
  • 合并所有行,在merged_lines中执行正则表达式匹配并稍后再次拆分它们以执行每行匹配是否会太昂贵?因为可能有多个文本模式块可以被替换,并且会减少逐行分析的文件长度。
  • 你可以测试不同的变体——接下来你可以做的是确定瓶颈(cpu -> 通过拆分源文件或工作流来尝试多处理;IO -> 首先将所有内容加载到内存中)跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-01
  • 2018-09-17
  • 2012-06-24
  • 1970-01-01
  • 2019-01-07
相关资源
最近更新 更多