我正在尝试创建一个在我的主脚本后台运行计时器的方法:
def hello_world(self):
print 'Hello!'
threading.Timer(2,hello_world).start()
if __name__ == "__main__":
try:
hello_world()
except KeyboardInterrupt:
print '\nGoodbye!'
当我尝试键盘中断我的脚本时,我收到此消息:
Exception KeyboardInterrupt in <module 'threading' from '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py'> ignored
如何关闭线程以便我可以干净地退出应用程序?
答案 0 :(得分:12)
要详细说明Aphex的答案,主线程不可能捕获KeyboardInterrupt信号,除非你手指非常快。主线程几乎立即退出!试试这个:
import threading
def hello_world():
print 'Hello!'
threading.Timer(2,hello_world).start()
if __name__ == "__main__":
try:
hello_world()
except KeyboardInterrupt:
print '\nGoodbye!'
print "main thread exited"
更一般地说,我不建议像这样使用自调用计时器,只是因为它创建了很多线程。只需创建一个线程并在其中调用time.sleep
。
但是,只要你保持主线程运行,你似乎能够在内部捕获KeyboardInterrupt
。然后,技巧是使线程成为主线程退出时退出的daemon
线程。
import threading
import time
def hello_world():
while(True):
print 'Hello!'
time.sleep(2)
if __name__ == "__main__":
hw_thread = threading.Thread(target = hello_world)
hw_thread.daemon = True
hw_thread.start()
try:
time.sleep(1000)
except KeyboardInterrupt:
print '\nGoodbye!'
这会在1000秒后自动退出 - 如果您愿意,可以使该数字更大。您也可以使用忙循环重复睡眠呼叫,但我真的没有看到这一点。
答案 1 :(得分:7)
您只需将data
主题设置为Timer
daemon
这将导致它在主线程退出时退出,例如由于def hello_world(self):
print 'Hello!'
t = threading.Timer(2,hello_world)
t.daemon = True
t.start()
。
KeyboardInterrupt
设置导致整个程序在剩下的唯一线程为daemon
个线程时退出。
答案 2 :(得分:2)
尝试重新引发KeyboardInterrupt
例外:http://effbot.org/zone/stupid-exceptions-keyboardinterrupt.htm
但这仍然可能不起作用;你有可能遇到这个caveat:
线程与中断奇怪地交互:KeyboardInterrupt异常将由任意线程接收。 (当信号模块可用时,中断始终转到主线程。)
简而言之,您无法确定KeyboardInterrupt
是否会转到主线程。要解决此问题,您可能需要查看signal
模块。
编辑:取消线程的一种更优雅的方法是拥有一个线程所看到的共享变量,并在它变为false
时退出。然后,如果要从主线程中终止线程,则将变量设置为false
。