Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python:如何中断正则表达式匹配_Python_Regex_Multithreading_Timeout_Signals - Fatal编程技术网

python:如何中断正则表达式匹配

python:如何中断正则表达式匹配,python,regex,multithreading,timeout,signals,Python,Regex,Multithreading,Timeout,Signals,我在大量下载的文本文件中迭代这些行,并在每行上进行正则表达式匹配。通常,比赛不到一秒钟。然而,有时一场比赛需要几分钟,有时比赛根本没有结束,代码只是挂起(等了几次一个小时,然后就放弃了)。因此,我需要引入某种超时,并以某种方式告诉正则表达式匹配代码在10秒左右后停止。我可以接受这样一个事实:我将丢失正则表达式应该返回的数据 我尝试了以下方法(当然,在一个代码示例中已经显示了两种不同的基于线程的解决方案): 但是我既没有得到名为的timeout\u处理程序,也没有得到输出中的行,代码只是停留在解析

我在大量下载的文本文件中迭代这些行,并在每行上进行正则表达式匹配。通常,比赛不到一秒钟。然而,有时一场比赛需要几分钟,有时比赛根本没有结束,代码只是挂起(等了几次一个小时,然后就放弃了)。因此,我需要引入某种超时,并以某种方式告诉正则表达式匹配代码在10秒左右后停止。我可以接受这样一个事实:我将丢失正则表达式应该返回的数据

我尝试了以下方法(当然,在一个代码示例中已经显示了两种不同的基于线程的解决方案):

但是我既没有得到名为的
timeout\u处理程序,也没有得到输出中的
行,代码只是停留在
解析数据文件中

更糟糕的是,我甚至不能用
CTRL-C
停止程序,而是需要查找python进程号并终止该进程。一些研究表明,Python的人知道正则表达式C代码正在流失:

我确实在使用信号方面取得了一些成功:

signal(SIGALRM, timeout_handler)
alarm(8)
data_sets = parse_data_files(config(), data_provider)
alarm(0)
这将获得输出中名为
行的
timeout\u处理程序,我仍然可以使用
CTRL-C
停止脚本。如果我现在修改超时\u处理程序,如下所示:

class TimeoutException(Exception): 
    pass 

def timeout_handler(signum, frame):
    raise TimeoutException()
并将对
re.match(…)
的实际调用包含在
try
中<除了TimeoutException
子句之外,正则表达式匹配实际上会被中断。不幸的是,这只适用于我用来尝试东西的简单的单线程沙盒脚本。此解决方案存在一些问题:

  • 信号只会触发一次,如果有多条线路有问题,我会被卡在第二条线路上
  • 计时器就在那里开始计数,而不是在实际解析开始时
  • 由于GIL,我必须在主线程中进行所有信号设置,并且信号仅在主线程中接收;这与多个文件要在单独的线程中同时解析的事实相冲突——也只引发了一个全局超时异常,我不知道如何知道需要在哪个线程中对其作出反应
  • 我已经读过好几次了,线程和信号不能很好地混合
我也考虑过在一个单独的过程中进行正则表达式匹配,但是在我开始之前,我想我最好在这里检查一下是否有人曾经遇到过这个问题,并可以给我一些关于如何解决这个问题的提示

更新 正则表达式如下所示(不管怎样,其中一个正则表达式也会出现问题;这是最简单的正则表达式):

“^(\d{5}),.+?,(\d{8}),(\d{4}),.+?,.+?,“+37*”(.*?,“+”(.*?)$”

样本数据:

95756,“KURN”,201103112130,-34.00151.21260,06.0,-9999.0,-9999.0,-9999.0,-9999.0,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999

如前所述,正则表达式通常执行正常-我可以在不到一分钟内用几百行解析几百个文件。这时文件就完成了——代码似乎挂起了行不完整的文件,例如

`95142,“YMGD”,201103111700,-12.06134.23310,05.0,25.8,23.71004.7,20.6,0.0,-9999,-9999,07.0,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999,-9999

我也遇到过这样的情况,正则表达式似乎立即返回并报告不匹配

更新2 我只是很快地通读了一遍,但据我所知,这不是原因——我没有嵌套任何重复运算符


我在Mac OSX上,所以我不能使用RegexBuddy分析我的regex。我尝试过(显然它在内部使用Perl正则表达式引擎),但也没有成功。

你不能用线程来完成。继续你的想法,在一个单独的过程中进行匹配。

Python中的线程是一个怪兽。全局解释器锁本质上是解释器周围的一个大锁,这意味着每次只有一个线程在解释器内执行

线程调度委托给操作系统。Python本质上是向操作系统发出信号,表示另一个线程可能在执行了一定数量的“指令”后获得锁。因此,如果Python由于一个失控的正则表达式而忙,它就永远不会有机会向操作系统发出信号,表示它可能试图为另一个线程获取锁。因此,使用信号的原因;他们是打断别人的唯一方式


我是Nosklo的,继续使用单独的流程。或者,尝试重写正则表达式,使其不会跑掉。看见这可能是也可能不是regex性能不佳的原因,并且不可能更改您的regex。但是,如果这是原因,而且可以改变,那么你可以避免多个过程来减轻你自己的头痛。

而不是试图用超时解决ReGEXP挂断问题,也许值得考虑一种完全不同的方法。如果数据实际上只是逗号分隔的值,那么使用-module或仅仅使用

line.split(“,”
)应该可以获得更好的性能,因为您将遇到灾难性的回溯;不是因为嵌套的量词,而是因为你的量化字符也可以匹配分隔符,而且因为有很多分隔符,在某些情况下你会得到指数时间

除了看起来更像CSV解析器的作业之外,请尝试以下操作:

r'^(\d{5}), [^,]+, (\d{8}), (\d{4}), [^,]+, [^,]+,' + 37 * r' ([^,]+),' + r' ([^,]+)$'
通过明确禁止逗号在分隔符之间匹配,您将极大地提高正则表达式的速度

例如,如果逗号可能出现在带引号的字符串中,则只需交换
[^,]+
(在
r'^(\d{5}), [^,]+, (\d{8}), (\d{4}), [^,]+, [^,]+,' + 37 * r' ([^,]+),' + r' ([^,]+)$'
(?:"[^"]*"|[^,]+)