繁体   English   中英

为什么我的线程/多处理python脚本没有正确退出?

[英]Why is my threading/multiprocessing python script not exiting properly?

我有一个服务器脚本,我需要能够干净地关闭。 在测试通常的try..except语句时,我意识到Ctrl-C没有按常规方式工作。 通常我会像这样包装长时间运行的任务

try:
    ...
except KeyboardInterrupt:
    #close the script cleanly here

所以可以在Ctrl-C上干净地关闭任务。 我之前从未遇到过任何问题,但是当我按下Ctrl-C时,当这个特定的脚本运行时,脚本只是退出而没有捕获Ctrl-C

初始版本是使用multiprocessing Process实现的。 我使用Threadthreading重写脚本,但同样的问题。 我以前曾多次使用过threading ,但我是multiprocessing库的新手。 无论哪种方式,我以前从未经历过这种Ctrl-C行为。

通常我总是实现了哨兵等以有序的方式关闭QueuesThread实例,但是这个脚本只是退出而没有任何响应。

最后,我尝试覆盖signal.SIGINT ,就像这样

def handler(signal, frame):
    print 'Ctrl+C'

signal.signal(signal.SIGINT, handler)
...

这里实际上是Ctrl+C被捕获,但处理程序没有执行,它从不打印任何东西。

除了threading / multiprocessing方面,脚本的一部分包含C++ SWIG对象。 我不知道这与它有什么关系。 我在OS X Lion上运行Python 2.7.2。

那么,有几个问题:

  1. 这里发生了什么?
  2. 我该怎么调试呢?
  3. 为了解根本原因,我需要学习什么?

请注意:脚本的内部是专有的,所以我不能给出代码示例。 然而,我非常愿意接收指针,所以我可以自己调试。 如果有人能指出我正确的方向,我有足够的经验能够弄明白。

编辑:我开始评论导入等,看看是什么导致了奇怪的行为,我把它缩小到导入C++ SWIG库。 为什么导入C++ SWIG库'窃取' Ctrl-C想法? 我不是有罪图书馆的作者,但我的SWIG经验有限,所以不知道从哪里开始......

编辑2:我刚刚在Windows机器上尝试了相同的脚本,在Windows 7中Ctrl-C预期捕获了Ctrl-C 我真的不打算使用OS X部分,无论如何,脚本都将在Windows环境中运行。

这可能与Python管理线程,信号和C调用的方式有关。

简而言之 - Ctrl-C不能中断C调用,因为实现要求python线程将处理信号,而不仅仅是任何线程,而是主线程 (经常被阻塞,等待其他线程)。

事实上,长时间的操作可以阻止一切。

考虑一下:

>>> nums = xrange(100000000)
>>> -1 in nums
False (after  ~ 6.6 seconds)
>>>

现在,尝试按Ctrl-C(不间断!)

>>> nums = xrange(100000000)
>>> -1 in nums
^C^C^C   (nothing happens, long pause)
...
KeyboardInterrupt
>>>

Ctrl-C不适用于线程程序的原因是主线程经常被阻塞在不间断的线程连接或锁定上(例如,任何'等待','连接'或只是一个普通的空'主'线程,在后台导致python在任何生成的线程上“加入”。

尝试插入一个简单的

while True:
    time.sleep(1)

在你的主线程中。

如果你有一个长时间运行的C函数,那就用C级进行信号处理(愿力量与你在一起!)。

这主要基于David Beazley关于这个主题的视频

它退出是因为其他东西可能会捕获KeyboardInterupt然后引发其他异常,或者只是返回None。 您仍然应该获得回溯以帮助调试。 您需要捕获stderr输出或使用-i命令行选项运行脚本,以便查看回溯。 另外,添加另一个除了块以捕获所有其他异常。

如果你怀疑C ++函数调用捕获CTRL + C尝试捕获它的输出。 如果C函数没有返回任何内容,那么除了要求作者添加一些异常处理,返回代码等之外,您无能为力。

try:
    #Doing something proprietary  ...
    #catch the function call output
    result = yourCFuncCall()

    #raise an exception if it's not what you expected
    if result is None:
        raise ValueError('Unexpected Result')

except KeyboardInterupt:
    print('Must be a CTRL+C')
    return

except:
    print('Unhandled Exception')
    raise

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM