【问题标题】:looking for practical solutions for optimizing text parsing speed with python寻找使用python优化文本解析速度的实用解决方案
【发布时间】:2011-05-28 10:02:00
【问题描述】:

需要使用一组不同的命名正则表达式来解析行集。

每一行都通过每个正则表达式,直到找到匹配。 当找到匹配时,代码应该为每一行返回/产生(命名的正则表达式,值)对。

文件大小超过 2GB,因此我正在寻找一些想法来提高解析器的速度。

目前代码是通过 python 执行的,但该部分可以更改。 一种选择是将所有内容都转换为 C 以从 PCRE 和更快的(?) IO 中获得更快的速度,但这是一条在未来难以维护的缓慢路线。

我正在寻找实用的解决方案,例如:

  • 将解析器转换为更快的语言
  • 迁移到 cython (?)
  • 将文件拆分成多个块并在几个线程之上运行

【问题讨论】:

  • “解析”这个词不是暗示您不得使用正则表达式吗?它们不适合任何类型的解析
  • 别挑剔了,我需要解决问题,如果你有更好的词来解释我的问题,请提出建议。
  • 我建议的是更好的解决方案,而不是更好的词。使用任何适当的解析器生成器,编写自己的简单递归下降解析器,无论如何,但不要使用正则表达式进行解析,它们不是为此目的而设计的。您可以将它们用于词法分析,如果您的所有模式共享同一组可能的词法标记,那么您将获得线性扫描速度。
  • 我必须承认你有一个观点。你能推荐一些我可以与 python / linux 组合使用的解析器生成器吗?毕竟指向这一点是为了让这一切更快......
  • 正如您所说,您可能会考虑选择另一种语言 - 因此,可以选择 lex 和 yacc 的旧组合(两者都快如闪电)。否则,有很多选择,包括 PLY、Yapps 以及来自 wiki.python.org/moin/LanguageParsing 的所有东西

标签: python parsing optimization text-parsing


【解决方案1】:

首先,我不会担心切换到另一种语言。替代策略可能会产生更大的收益。 python使用的正则表达式引擎无论如何都是用C编写的(iirc)。

  1. “优化”正则表达式可能是您的第一项任务。如何做到这一点取决于您的文本和表达方式。有文章和示例的look。 @ThomasH 也提出了一个很好的观点。
  2. 优化正则表达式的最简单方法是删除它;看看是否有机会切换到其他测试,例如x in yline.endswith() 等。
  3. 尝试使用pypy 运行您的代码。它可以在不修改代码的情况下获得性能提升。在您的情况下,尽管收益可能微不足道,因为性能与您的正则表达式和文件 io 的性能绑定。
  4. 跨多个线程/进程并发处理文件可能是有益的。我建议使用一个进程来读取文件并将行推送到多个进程从中提取的队列中。有很多方法可以做到这一点。看看http://effbot.org/zone/wide-finder.htm#a-multi-processor-python-solution

【讨论】:

    【解决方案2】:

    在 Python 中加快模式匹配的一个重要点是尝试使用 single 正则表达式。因此,与其为每一行输入查看一个正则表达式列表,不如将这些正则表达式与| 合并为一个,然后对每一行应用一次这个正则表达式:

    reg = re.compile(r'''
        (?<patt1>foo)
        |(?<patt2>bar)
    ''', re.VERBOSE)
    
    for line in lines:
        mo = reg.search(line)
        if mo:
            yield (mo.lastgroup(), mo.group(mo.lastgroup()))
    

    【讨论】:

    • 这在我能做的一些优化中是有意义的,tnx
    【解决方案3】:

    我想到的第一件事是你应该使用 re.compile() 来准备所有的正则表达式。但我想这已经完成了!

    要考虑的另一件事可能是分层处理:

    根据您拥有的正则表达式的类型,它们可以分层组织。这样您就可以预先过滤这些行,然后只将它们输入到您需要检查的正则表达式中。

    例如,如果您在正则表达式中搜索“

    ”之类的标签,则在检查它是否真的是标签之前,在该行中搜索“body”可能会有所帮助。您也可以在使用标签相关的正则表达式之前搜索“

    如果您将多个表达式合并为一个并检查匹配,它也可以加快处理速度。就像用“{(term1|term2)}”替换“{term1}”“{term2}”的单个检查一样。

    然后您可以尝试通过定义它们工作的最小行长度来过滤需要检查的正则表达式。

    这样的简单事情可以在不切换到另一种语言或 cpu 的情况下加速您的应用程序。

    如果可能,您也可以尝试使用多线程。根据 CPU 的利用率,您可以在两个线程中处理每隔一行,这也可以大大加快处理速度。

    【讨论】:

    • re 表达式由 python 在内部自动编译,并在任何后续调用中按顺序使用
    • hmm..tnx 获取信息,我会尝试使用 compile() 对我的解析器进行计时,看看它是否能改善这种情况..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多