首页 > 编程问答 >使用 callable_iterator (re.finditer) 导致 Python 冻结

使用 callable_iterator (re.finditer) 导致 Python 冻结

时间:2024-07-22 08:14:04浏览次数:11  
标签:python python-3.x regex loops freeze

我有一个为文本的每一行调用的函数。

def tokenize_line(line: str, cmd = ''):
    matches = re.finditer(Patterns.SUPPORTED_TOKENS, line)
    tokens_found, not_found, start_idx = [], [], 0
    print(matches)
    for match in matches:
        pass
        # Rest of code

print(matches) 的结果类似于: <callable_iterator object at 0x0000021201445000>

但是,当我将迭代器转换为列表时:

matches = list(re.finditer(Patterns.SUPPORTED_TOKENS, line))

或者当我用 | 进行迭代时||: for ...Python 冻结。

for match in matches:
   print(match)

此问题的发生不一致。例如:

因此,当将 callable_iterator 转换为列表或对其进行迭代时,就会出现问题。

tokenize_line('$color AS $length') # Works fine
tokenize_line('FALSE + $length IS GT 7 + $length IS 4') # Freezes

这是我正在使用的模式 (Patterns.SUPPORTED_TOKENS):

正则表达式模式的说明:

(°p\d+°|°a\d+°|°m\d+°)|((?<!\S)(?:!\'(?:\\.|[^\'\n\\])*\'|!"(?:\\.|[^\n"\\])*")(?!\S))|((?:\'(?:\\.|[^\'\n\\])*\'|"(?:\\.|[^\n"\\])*"))|((\{(.*)\}))|((?<!\S)([@$][\w]*(?:\.[\w]*)*)(?!\S))|((?<!\d)-?\d*\.?\d+)|(\*\*|[\+\-\*\(\)/%\^]|==|&&|\|\||!=|>=|<=|>|<|~~|!~~|::|!::)|([\:/])|(\b(?:AS|AND|AT|:|BETWEEN|BY|FROM|IN|INTO|ON|OF|OR|THAN|TO|USING|WITH)\b)|(\b[a-zA-Z_][a-zA-Z0-9_]* *((?:[^;()\'""]*|"(?:[^"\\]|\\.)*"|\'(?:[^\'\\]|\\.)*\'|\([^)]*\))*?;))|((\b(?:EMPTY|STRING|NUMBER|BOOL|ARRAY|MAP|TRUE|FALSE|NULL|UNKNOWN|DOTALL|IGNORECASE|MULTILINE|ARRAY_ARRAY|ARRAY_STRING|ARRAY_MAP|ARRAY_NUMBER|ARRAY_NULL|DOT|SPACE|NEWLINE|SEMICOLON|COLON|HASH|COMMA|TAB)\b)|(\b(?:IS NOT LT|IS NOT GT|IS NOT GEQ|IS NOT LEQ|IS NOT|IS LT|IS GT|IS GEQ|IS LEQ|IS|NOT IN|NOT|IN|HAS NOT|HAS|AND|OR)\b))

自定义标记:

匹配以特定字符开头并后跟数字的特定自定义标记。 带引号的字符串:

匹配单引号和双引号字符串,包括带有转义字符的字符串。 大括号内容:匹配大括号内的任何内容。 变量:

匹配以特定字符(如 @ 或 $)开头的变量,并且可以包含嵌套属性的点。 数字:

同时匹配整数和浮点数,包括负数。 运算符:

匹配各种数学和逻辑运算符。 冒号和斜杠:匹配特定的标点符号,例如冒号和斜杠。 关键字:

匹配语言中保留的某些关键字。 函数定义:匹配函数定义或类似结构,确保它们遵循特定的语法规则。 数据类型和修饰符:

匹配表示数据类型或修饰符的关键字。 逻辑运算符:

匹配复杂逻辑运算符在条件表达式中使用。 任何帮助理解为什么会发生这种情况以及如何修复它的帮助将不胜感激!

Any help to understand why this happens and how to fix it would be greatly appreciated!


Python 冻结的问题,特别是当它与特定输入字符串有关但没有引发错误时,通常表示正则表达式中存在导致灾难性回溯的问题。灾难性回溯发生在正则表达式引擎在尝试所有可能的匹配组合时陷入困境时,从而导致指数级长的执行时间。

的正则表达式很长且很复杂,因此很难确定导致问题的具体原因。但是,有一些部分特别容易受到灾难性回溯的影响:

  1. 嵌套量词和交替运算符: ((?:[^;()'""]*|"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*'|([^)]*)*))* 这样的模式在与输入字符串不匹配时,可能会导致大量的回溯。因为有很多种方法可以使用不同的交替组合来匹配或不匹配子字符串,所以引擎必须尝试所有组合,从而导致指数级复杂度。

  2. 过于宽泛的匹配: .* [^;()'""]* 这样的模式可以匹配非常多的字符,这也可能导致大量的回溯。例如,如果 .* 的意图是仅匹配单行内的任何内容,则应将其替换为 [^;\n]*

如何调试和修复此问题:

  1. 简化正则表达式: 尝试将的正则表达式分解为更小、更具体的模式。这将使更容易识别导致问题的部分。
  2. 使用非捕获组: 除非需要捕获子模式,否则请对不参与最终结果的组使用非捕获组 (?:...) 。这可以提高性能并减少回溯。
  3. 使量词更具体: 避免使用过于宽泛的量词,例如 * + ,尤其是在嵌套模式中。尝试使用更具体的量词,例如 {1,3} {0,1} ,或使用字符类来限制匹配的字符,例如 [a-z0-9]
  4. 使用正则表达式调试器: 有许多在线工具可以帮助可视化正则表达式的工作方式并识别潜在问题。例如, https://regex101.com/ https://debuggex.com/
  5. 考虑使用其他解析方法: 如果的正则表达式过于复杂,可能需要考虑使用其他解析方法,例如编写自定义解析器。

对于的具体情况,可以尝试以下操作:

  1. 分析导致冻结的输入字符串: 确定导致问题的特定输入字符串,并尝试隔离导致冻结的正则表达式部分。
  2. 逐步简化正则表达式: 从一个简化的正则表达式版本开始,然后逐渐添加复杂性,每次添加后测试性能。这将帮助确定导致问题的具体部分。
  3. 使用正则表达式调试器: 使用正则表达式调试器可视化引擎如何处理的模式和输入字符串。这可以帮助识别回溯发生的位置以及原因。

总而言之,解决正则表达式中的灾难性回溯问题可能很棘手,但这通常是通过仔细分析模式、简化模式和使用适当的工具来实现的。

标签:python,python-3.x,regex,loops,freeze
From: 78776597

相关文章

  • Python 的 time.sleep - 永远不会醒来
    我认为这将是那些简单的问题之一,但它让我感到困惑。[停止媒体:我是对的。找到了解决方案。查看答案。]我正在使用Python的单元测试框架来测试多线程应用程序。很好而且很直接-我有5个左右的工作线程监视一个公共队列,以及一个为它们制作工作项的生产者线程......
  • python中使用mitmproxy的http模块出错
    我有一个使用mitmproxyhttp函数的代码,它在这里惨败:defmain(stdscr):try:parser=argparse.ArgumentParser(description='NetSourNetworkAnalyzer')parser.add_argument('--proxy',action='store_true',help='EnableH......
  • 使用python图像去噪没有获得所需的重建图像
    我是python机器学习的初学者,我正在编写一个程序,使图像变得嘈杂,然后我的程序输出重建的图像。我正在使用加性高斯白噪声并使用前馈神经网络。我的程序显示真实图像、噪声图像和重建图像。这些是我通常得到的结果。有人知道如何解决这样的问题吗?这是我的代码:ap......
  • 使用 pip 22.3.1 和 python 3.11.0 安装 MetaTrader5 错误
    我正在尝试使用pip在Windows上安装MetaTrader5。python--versionPython3.11.0pip--versionpip22.3.1pipinstallMetaTrader5ERROR:CouldnotfindaversionthatsatisfiestherequirementMetaTrader5(fromversions:none)ERROR:Nomatchingdistribu......
  • 在 Python 中溶解线条
    我有一个包含多行的形状文件。我正在寻找一种方法来消除所有的接触线。这在ArcMap中是可能的,但似乎在Python和QGIS中都无法做到:之前:所需的输出:这需要在多行上完成,因此像QGIS合并一样手动执行不是一个选项。在ArcMap中,我曾经使用“溶解”......
  • 一个简单的问题(python、串行通信和arduinos)
    只是一个关于小脚本的快速问题,由于某种原因无法工作我运行了这个脚本:importserialimporttimeimportturtledefserialreading():serialPort=serial.Serial(port="COM5",baudrate=9600,bytesize=8,timeout=2,stopbits=serial.STOPBITS_ONE......
  • 我在 Windows 10 上运行 Python 代码后控制台立​​即关闭
    虽然我在代码末尾使用input(),但在Windows10(IDLE之外)的窗口中输入名称后,控制台仍然立即关闭,并且我看不到结果。我该怎么做才能阻止控制台关闭?#!python3name=input('Enteryourname:')print('Hello'+name)input('pressEntertoexit:')你在代码末尾......
  • 具有未定义嵌套列表深度的嵌套列表的Python注释类型
    [[1,2,3],3,[2,4],5]的类型是list[list[int]|int]但是,如果嵌套列表具有未定义的深度,例如[[[1,2]],2,[1,[3,[3]]]],3,[2,[2]]],那么它会具有什么类型?可以使用递归类型提示来表示任意深度嵌套的列表:fromtypingimportList,Union......
  • 在Spyder(Python 3.6)中导入cv2时出现导入错误
    我已经在Windows操作系统中安装了opencv3.0.0。我已运行该应用程序并已成功将其安装在C:\驱动器中,并且还将cv2.pyd文件复制到C:\Python27\Lib\site-packages中,正如我在几个教程视频中看到的那样在我的Python2.7.5Shell中,即当我键入>>>i......
  • Python + VS Code 调试器:可视化我的程序当前正在执行的源代码中的位置?
    当我使用VSCodePython调试器时:我可以执行我的程序,以便编辑器将我逐行带到源代码中的任何位置(跳转到相关文件/如果尚未打开则将其打开)目前的执行情况是?是的,VSCode的Python调试器可以让你逐行执行代码,并实时显示当前执行的位置。以下是操作方法:1.设置断点:......