问题描述
我正在 Windows 上编写多线程 Python 应用程序.
I'm writing a multithreaded Python app on Windows.
我曾经使用 ctrl-c
终止应用程序,但是一旦我添加了 threading.Timer
实例 ctrl-c
停止工作(或有时需要很长时间).
I used to terminate the app using ctrl-c
, but once I added threading.Timer
instances ctrl-c
stopped working (or sometimes takes a very long time).
这怎么可能?
拥有 Timer 线程和 ctrl-c
之间有什么关系?
How could this be?
What's the relation between having Timer threads and ctrl-c
?
更新:
我在 Python 的 线程文档 中发现了以下内容:
线程与中断:KeyboardInterrupt异常将收到任意线程.(当信号模块可用,中断总是转到主线程.)
推荐答案
threading.Thread
(以及因此 threading.Timer
)的工作方式是每个线程注册自己使用 threading
模块,并且在解释器退出时,解释器将等待所有注册的线程退出,然后才能正确终止解释器.这样做是为了让线程真正完成执行,而不是将解释器从它们下面残酷地移除.所以当你点击 ^C 时,主线程接收到信号,决定终止并等待定时器完成.
The way threading.Thread
(and thus threading.Timer
) works is that each thread registers itself with the threading
module, and upon interpreter exit the interpreter will wait for all registered threads to exit before terminating the interpreter proper. This is done so threads actually finish execution, instead of having the interpreter brutally removed from under them. So when you hit ^C, the main thread receives the signal, decides to terminate and waits for the timers to finish.
您可以设置线程 daemonic(使用 setDaemon
方法)使线程模块不等待这些线程,但如果它们碰巧在执行 Python 代码时解释器退出时,您会在退出时遇到令人困惑的错误.即使你取消了 threading.Timer
(并将其设置为守护进程)它仍然可以在解释器被销毁时唤醒——因为 threading.Timer
的 cancel
方法只是告诉 threading.Timer
在它唤醒时不要执行任何操作,但它必须实际执行 Python 代码才能做出决定.
You can set threads daemonic (with the setDaemon
method) to make the threading module not wait for these threads, but if they happen to be executing Python code while the interpreter exits, you get confusing errors during exit. Even if you cancel the threading.Timer
(and set it daemonic) it can still wake up while the interpreter is being destroyed -- because threading.Timer
's cancel
method just tells the threading.Timer
not to execute anything when it wakes up, but it has to actually execute Python code to make that determination.
没有优雅的方式来终止线程(当前线程除外),也没有可靠的方式来中断被阻塞的线程.更易于管理的计时器方法通常是事件循环,就像 GUI 和其他事件驱动系统为您提供的那样.使用什么完全取决于还有什么你的程序会做什么.
There is no graceful way to terminate threads (other than the current one), and no reliable way to interrupt a thread that's blocked. A more manageable approach to timers is usually an event loop, like the ones GUIs and other event-driven systems offer you. What to use depends entirely on what else your program will be doing.
这篇关于使用 threading.Timer 时 Ctrl-C 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!