Python - 取消计时器线程

时间:2011-05-10 15:57:38

标签: python

我正在尝试创建一个在我的主脚本后台运行计时器的方法:

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

如何关闭线程以便我可以干净地退出应用程序?

3 个答案:

答案 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