【发布时间】:2012-02-13 22:59:39
【问题描述】:
在多线程 Python 程序中,一个线程有时会使用内置的 raw_input() 请求控制台输入。我希望能够通过在 shell 中键入 ^C(即使用 SIGINT 信号)在 raw_input 提示符下关闭程序。但是,当子线程正在执行 raw_input 时,键入 ^C 什么也不做——直到我按下回车键(离开 raw_input)时才会引发 KeyboardInterrupt。
例如,在以下程序中:
import threading
class T(threading.Thread):
def run(self):
x = raw_input()
print x
if __name__ == '__main__':
t = T()
t.start()
t.join()
在输入完成之前,键入 ^C 不会执行任何操作。但是,如果我们只是调用T().run()(即单线程情况:在主线程中运行raw_input),^C 会立即关闭程序。
大概是因为 SIGINT 被发送到主线程,主线程被挂起(等待 GIL),而分叉线程在控制台读取时阻塞。主线程在 raw_input 返回后获取 GIL 之前不会执行其信号处理程序。 (如果我对此有误,请纠正我——我不是 Python 线程实现方面的专家。)
有没有办法以类似 raw_input 的方式从标准输入读取数据,同时允许 SIGINT 由主线程处理,从而降低整个进程?
[我在 Mac OS X 和一些不同的 Linux 上观察到上述行为。]
编辑:我错误地描述了上面的根本问题。在进一步调查中,阻止信号处理的是主线程对join() 的调用:Guido van Rossum 本人已经解释过the underlying lock acquire in join is uninterruptible。这意味着信号实际上被推迟到整个线程完成 - 所以这实际上与 raw_input 完全无关(只是后台线程正在阻塞,因此连接没有完成)。
【问题讨论】:
-
一个不简单的结合线程和中断... [boromir.jpg]
标签: python input python-multithreading sigint control-c