adr*_*ian 8 python input sigint control-c python-multithreading
在多线程Python程序中,一个线程有时会使用内置的raw_input()来请求控制台输入.我希望能够在raw_input提示符下通过在shell中键入^ C来关闭程序(即,使用SIGINT信号).但是,当子线程正在执行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()
Run Code Online (Sandbox Code Playgroud)
键入^ C在输入完成之前不会执行任何操作.但是,如果我们只是调用T().run()(即,单线程情况:只在主线程中运行raw_input),^ C立即关闭程序.
据推测,这是因为SIGINT被发送到主线程,它被挂起(等待GIL),而分支线程在控制台上阻塞读取.主线程在raw_input返回后抓取GIL之前不会执行其信号处理程序.(如果我错了,请纠正我 - 我不是Python线程实现方面的专家.)
有没有办法以类似raw_input的方式从stdin读取,同时允许主线程处理SIGINT,从而降低整个过程?
[我在Mac OS X和一些不同的Linux上观察到了上述行为.]
编辑:我错误地描述了上面的根本问题.在进一步调查中,主要线程的呼吁join()是阻止信号处理:Guido van Rossum本人已经解释说,加入中的底层锁定是不可中断的.这意味着信号实际上被推迟到整个线程完成 - 所以这实际上完全没有任何关系raw_input(只是后台线程阻塞以便连接没有完成的事实).
当调用join时没有超时,它是不可中断的,但是当它被超时调用时,它是可中断的.尝试添加任意超时并将其置于while循环中:
while my_thread.isAlive():
my_thread.join(5.0)
Run Code Online (Sandbox Code Playgroud)
确实没有简单的方法可以解决这个问题。
一种方法是重新组织和分解代码,使需要可Ctrl-C中断性的函数部分在主线程上执行。您可以使用队列发送执行请求,同样也可以发送结果值。主线程需要一个输入队列,每个非主线程需要一个输出队列;和协调的主线程退出。显然,这种方式在任何给定时间只执行一个阻塞函数,这可能不是您想要的。
下面是这个想法的一个工作示例,其中稍微不正当地使用信号量来协调主线程退出。
| 归档时间: |
|
| 查看次数: |
2466 次 |
| 最近记录: |