守护程序线程说明


237

Python文档中 它说:

线程可以标记为“守护程序线程”。该标志的重要性在于,仅保留守护程序线程时,整个Python程序都会退出。初始值是从创建线程继承的。

没有人对这意味着什么有更清楚的解释,或者有实际的示例显示了将线程设置为的位置daemonic

为我澄清一下:因此,您唯一不希望将线程设置为的情况daemonic是,您希望它们在主线程退出后继续运行吗?

Answers:


447

一些线程执行后台任务,例如发送keepalive数据包,执行定期垃圾回收等。这些仅在主程序正在运行时才有用,并且可以在其他非守护程序线程退出后将其杀死。

如果没有守护程序线程,则必须跟踪它们,并告诉它们退出,然后程序才能完全退出。通过将它们设置为守护程序线程,可以让它们运行并忘记它们,并且在程序退出时,所有守护程序线程都会自动终止。


1
因此,如果我有一个正在执行设置为非守护进程的文件写入操作的子线程,这是否意味着我必须使其明确退出?
Ciasto piekarz 2014年

8
@san完成编写后,您的编写器线程会做什么?它会回来吗?如果是这样,那就足够了。守护线程通常用于循环运行且不会自行退出的事物。
克里斯·杰斯特·杨

它什么都不做,也不返回,其唯一目的是执行文件写操作
Ciasto piekarz 2014年

2
@san如果不属于线程函数的底部,则将隐式返回。
克里斯·杰斯特·杨

None在这种情况下会返回,但没关系,不使用返回值。
克里斯·杰斯特·杨

30

假设您正在制作某种仪表板小部件。作为其一部分,您希望它在您的电子邮件框中显示未读邮件数。因此,您将创建一个小线程,该线程将:

  1. 连接到邮件服务器,并询问您有多少未读邮件。
  2. 用更新的计数向GUI发出信号。
  3. 睡一会儿。

当您的小部件启动时,它将创建此线程,将其指定为守护程序,然后启动它。因为它是一个守护程序,所以您不必考虑它。当您的小部件退出时,线程将自动停止。


18

其他张贴者提供了一些有关使用守护程序线程的情况的示例。但是,我的建议是永远不要使用它们。

不是因为它们没有用,而是因为如果使用它们,您会遇到一些不良的副作用。在Python运行时开始拆除主线程中的内容之后,守护程序线程仍然可以执行,从而导致一些非常奇怪的异常。

更多信息在这里:

https://joeshaw.org/python-daemon-threads-considered-harmful/

https://mail.python.org/pipermail/python-list/2005-February/343697.html

严格来说,您永远不需要它们,在某些情况下,它只是使实施更容易。


仍然是python 3的问题吗?在文档中没有有关这些“怪异例外”的明确信息。
kheraud

5
摘自Joe的博客文章:“ 2015年6月更新:这是Python错误1856。它已在Python 3.2.1和3.3中修复,但从未将其反向移植到2.x。(尝试向2.7分支反向移植导致了另一个错误守护进程线程在Python> = 3.2.1中可能还可以,但在早期版本中肯定不是。”
clacke

我想在这里分享我的经验:我有一个函数多次作为Thread产生。在它内部,我有一个Python实例,logging我希望在完成线程后,所有对象(每个线程/函数的文件描述符)都将被销毁。在程序结束时,我看到了许多输出,例如 IOError: [Errno 24] Too many open files:。使用lsof -p pid_of_program,我发现FD是打开的,即使Thread / Functions都完成了工作也很困难。解决方法?在函数末尾删除日志处理程序。所以daemonic线程是不值得信赖的...
ivanleoncz

17

一种更简单的思考方式可能是:当main返回时,如果仍有非守护进程线程仍在运行,则您的进程将不会退出。

一点建议:涉及线程和同步时,干净关闭很容易出错-如果可以避免,请这样做。尽可能使用守护程序线程。


13

克里斯已经解释了什么是守护程序线程,所以让我们谈谈实际用法。许多线程池实现将守护程序线程用于任务工作者。工作者是从任务队列执行任务的线程。

工作人员需要无限期地等待任务队列中的任务,因为他们不知道何时出现新任务。分配任务的线程(例如主线程)仅知道任务何时结束。主线程等待任务队列变空,然后退出。如果worker是用户线程,即非守护程序,则程序不会终止。即使工人没有做任何有用的事情,它将继续等待这些无限期地运转的工人。标记工人守护程序线程,主线程将在处理完任务后立即杀死它们。


4
小心点!如果程序向守护程序任务队列提交了重要任务(例如,在后台“更新”某个文件),则存在该程序可能在执行任务之前终止的风险,或者更糟的是在更新该文件的过程中终止。
所罗门慢慢片

10

引用克里斯:“ ...程序退出时,所有守护程序线程都会被自动杀死。”。我认为可以总结一下。使用它们时应小心,因为它们会在主程序执行完成时突然终止。


4

当您的第二个线程是非守护程序线程时,您的应用程序的主主线程无法退出,因为它的退出条件也与非守护程序线程的退出绑定在一起。无法在python中强制杀死线程,因此您的应用程序将必须真正等待非守护进程线程退出。如果这种行为不是您想要的,则将您的第二个线程设置为守护程序,这样它就不会阻止您的应用程序退出。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.