我有一个函数,我每隔5秒就会调用一次:
def check_buzz(super_buzz_words):
print 'Checking buzz'
t = Timer(5.0, check_buzz, args=(super_buzz_words,))
t.dameon = True
t.start()
buzz_word = get_buzz_word()
if buzz_word is not 'fail':
super_buzz_words.put(buzz_word)
main()
check_buzz()
我通过捕获KeyboardInterrupt或捕获系统出口并调用它来退出脚本:
sys.exit('\nShutting Down\n')
我也经常致电:
重启程序execv(sys.executable, [sys.executable] + sys.argv)
我的问题是,如何让计时器线程关闭?如果我键盘中断,计时器继续运行。
答案 0 :(得分:1)
我认为您只是将守护程序的拼写错误,应该是:
t.daemon = True
然后sys.exit()应该可以工作
答案 1 :(得分:0)
from atexit import register
def all_done():
if t.is_alive():
# do something that will close your thread gracefully
register(all_done)
基本上,当您的代码即将退出时,它将触发最后一个函数,您将在此处检查您的线程是否仍在运行。如果是,请执行取消交易或以其他方式优雅退出的操作。一般来说,最好让线程自己完成,但如果它没有做任何事情重要(请注意重点),而不是你可以做t.cancel()
。设计你的代码,以便线程尽可能自己完成。
答案 2 :(得分:0)
另一种方法是使用Queue()模块使用线程外部的.put()和线程内的.get()从线程发送和接收信息。 您还可以做的是创建一个txt文件并在退出时让程序写入它并在每次迭代后在线程函数中放置一个if语句来检查它(这不是一个非常好的解决方案,但它也有效) 我会把一个代码例子,但我写的是移动抱歉
答案 3 :(得分:0)
扩展来自 notorious.no 的答案,以及评论询问:
<块引用>如果我无法访问 t.cancel()
,我该如何调用 t
功能?
第一次创建 Timer
线程时,给它一个不同的 name
:
import threading
def check_buzz(super_buzz_words):
print 'Checking buzz'
t = Timer(5.0, check_buzz, args=(super_buzz_words,))
t.daemon = True
t.name = "check_buzz_daemon"
t.start()
尽管局部变量 t
很快超出了作用域,Timer
指向的 t
线程仍然存在并且仍然保留分配给它的 name
。>
然后您的 atexit
注册方法可以通过它的 name
识别此线程并取消它:
from atexit import register
def all_done():
for thr in threading._enumerate():
if thr.name == "check_buzz_daemon":
if thr.is_alive():
thr.cancel()
thr.join()
register(all_done)
在调用 join()
之后调用 cancel()
是基于 Cédric Julien 的 a StackOverflow answer。
但是,您的线程设置为守护进程。根据{{3}},不需要显式终止守护线程。