Ami*_*t S 22 python multithreading kill keyboardinterrupt
我在某处读到KeyboardInterrupt异常只在Python的主线程中引发.我还读到在子线程执行时主线程被阻塞.那么,这是否意味着CTRL+ C永远不会到达子线程.我尝试了以下代码:
def main():
try:
thread = threading.Thread(target=f)
thread.start() # thread is totally blocking (e.g., while True)
thread.join()
except KeyboardInterrupt:
print "Ctrl+C pressed..."
sys.exit(1)
def f():
while True:
pass # do the actual work
Run Code Online (Sandbox Code Playgroud)
在这种情况下,CTRL+ C对执行没有影响.它就像是无法收听信号.我理解这是错误的方式吗?有没有其他方法可以使用CTRL+ 杀死线程C?
小智 13
如果你想让主线程在加入时接收CTRL+ C信号,可以通过添加超时来join()调用.
以下似乎正在起作用(daemon=True如果您希望main实际结束,请不要忘记添加):
thread1.start()
while True:
thread1.join(600)
if not thread1.isAlive():
break
Run Code Online (Sandbox Code Playgroud)
web*_*bbi 10
你正在使用的问题是thread1.join(),这将导致你的程序等到该线程完成继续.
信号将始终被主进程捕获,因为它是接收信号的信号,它是具有线程的进程.
如你所示,你基本上运行一个没有线程功能的"普通"应用程序,因为你启动1个线程并等到它完成继续.
KeyboardInterrupt仅在每个进程的主线程中引发异常。但该方法Thread.join会阻塞调用线程,包括 KeyboardInterrupt 异常。这就是为什么Ctrl+C似乎没有效果。
解决问题的一个简单方法是使方法Thread.join超时以解锁KeyboardInterrupt异常,并使子线程成为守护线程,让父线程在退出时杀死它(非守护子线程不会被杀死,而是在退出时由其父线程加入):
def main():
try:
thread = threading.Thread(target=f)
thread.daemon = True # let the parent kill the child thread at exit
thread.start()
while thread.is_alive():
thread.join(1) # time out not to block KeyboardInterrupt
except KeyboardInterrupt:
print "Ctrl+C pressed..."
sys.exit(1)
def f():
while True:
pass # do the actual work
Run Code Online (Sandbox Code Playgroud)
如果控制子线程的代码,更好的解决方案是通知子线程正常退出(而不是像简单的解决方案那样突然退出),例如使用threading.Event:
def main():
try:
event = threading.Event()
thread = threading.Thread(target=f, args=(event,))
thread.start()
event.wait() # wait without blocking KeyboardInterrupt
except KeyboardInterrupt:
print "Ctrl+C pressed..."
event.set() # notify the child thread to exit
sys.exit(1)
def f(event):
while not event.is_set():
pass # do the actual work
Run Code Online (Sandbox Code Playgroud)