【发布时间】:2020-11-19 17:52:53
【问题描述】:
我有一个小的 Python 程序,它在 Python 3.7 和 Python 3.8 中的行为不同。我很难理解为什么。 Python 3.8 的 #threading changelog 没有解释这一点。
代码如下:
import time
from threading import Event, Thread
class StoppableWorker(Thread):
def __init__(self):
super(StoppableWorker, self).__init__()
self.daemon = False
self._stop_event = Event()
def join(self, *args, **kwargs):
self._stop_event.set()
print("join called")
super(StoppableWorker, self).join(*args, **kwargs)
def run(self):
while not self._stop_event.is_set():
time.sleep(1)
print("hi")
if __name__ == "__main__":
t = StoppableWorker()
t.start()
print("main done.")
当我在 Python 3.7.3 (Debian Buster) 中运行它时,我看到以下输出:
python test.py
main done.
join called
hi
程序自行退出。我不知道为什么会调用join()。
来自3.7的daemon documentation:
当没有活着的非守护线程时,整个 Python 程序退出。
但显然线程应该还活着。
当我在 Python 3.8.6 (Arch) 中运行它时,我得到了预期的行为。也就是说,程序一直在运行:
python test.py
main done.
hi
hi
hi
hi
...
3.8 的daemon documentation 声明与 3.7 相同:除非所有非守护线程都已加入,否则程序不应退出。
有人可以帮我理解发生了什么吗?
【问题讨论】:
-
如果您希望线程优雅地停止,请将它们设为非守护进程并使用合适的信号机制,例如事件
-
回复,“我不知道为什么会调用
join()。”你能不设置断点,并找出是谁调用的吗?或者,也许更简单,将print("join called")替换为会引发错误并转储堆栈的语句。 -
我不完全确定这是对 join 的正确使用,因为有人可能会抱怨 Python 像这样使用或不使用它是错误的。
join的目的是等待线程结束——而不是向线程发出信号应该结束。这正是 Python 使用它的方式。
标签: python multithreading