守护程序线程说明

问题:守护程序线程说明

Python文档中 它说:

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

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

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

In the Python documentation it says:

A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread.

Does anyone have a clearer explanation of what that means or a practical example showing where you would set threads as daemonic?

Clarify it for me: so the only situation you wouldn’t set threads as daemonic, is when you want them to continue running after the main thread exits?


回答 0

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

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

Some threads do background tasks, like sending keepalive packets, or performing periodic garbage collection, or whatever. These are only useful when the main program is running, and it’s okay to kill them off once the other, non-daemon, threads have exited.

Without daemon threads, you’d have to keep track of them, and tell them to exit, before your program can completely quit. By setting them as daemon threads, you can let them run and forget about them, and when your program quits, any daemon threads are killed automatically.


回答 1

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

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

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

Let’s say you’re making some kind of dashboard widget. As part of this, you want it to display the unread message count in your email box. So you make a little thread that will:

  1. Connect to the mail server and ask how many unread messages you have.
  2. Signal the GUI with the updated count.
  3. Sleep for a little while.

When your widget starts up, it would create this thread, designate it a daemon, and start it. Because it’s a daemon, you don’t have to think about it; when your widget exits, the thread will stop automatically.


回答 2

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

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

更多信息在这里:

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

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

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

Other posters gave some examples for situations in which you’d use daemon threads. My recommendation, however, is never to use them.

It’s not because they’re not useful, but because there are some bad side effects you can experience if you use them. Daemon threads can still execute after the Python runtime starts tearing down things in the main thread, causing some pretty bizarre exceptions.

More info here:

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

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

Strictly speaking you never need them, it just makes implementation easier in some cases.


回答 3

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

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

A simpler way to think about it, perhaps: when main returns, your process will not exit if there are non-daemon threads still running.

A bit of advice: Clean shutdown is easy to get wrong when threads and synchronization are involved – if you can avoid it, do so. Use daemon threads whenever possible.


回答 4

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

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

Chris already explained what daemon threads are, so let’s talk about practical usage. Many thread pool implementations use daemon threads for task workers. Workers are threads which execute tasks from task queue.

Worker needs to keep waiting for tasks in task queue indefinitely as they don’t know when new task will appear. Thread which assigns tasks (say main thread) only knows when tasks are over. Main thread waits on task queue to get empty and then exits. If workers are user threads i.e. non-daemon, program won’t terminate. It will keep waiting for these indefinitely running workers, even though workers aren’t doing anything useful. Mark workers daemon threads, and main thread will take care of killing them as soon as it’s done handling tasks.


回答 5

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

Quoting Chris: “… when your program quits, any daemon threads are killed automatically.”. I think that sums it up. You should be careful when you use them as they abruptly terminate when main program executes to completion.


回答 6

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

When your second thread is non-Daemon, your application’s primary main thread cannot quit because its exit criteria is being tied to the exit also of non-Daemon thread(s). Threads cannot be forcibly killed in python, therefore your app will have to really wait for the non-Daemon thread(s) to exit. If this behavior is not what you want, then set your second thread as daemon so that it won’t hold back your application from exiting.