守护线程在 Python 中非常有用,可用于运行对程序操作不至关重要的后台任务。它们允许你在后台运行任务而不必担心跟踪这些任务。
Python 提供了两种类型的线程:非守护线程和守护线程。默认情况下,线程是非守护线程。本教程提供了有关 Python 编程中守护线程的详细解释及相关示例。
守护线程概述
有时,有必要在后台执行一个任务。为此类后台任务专门使用了一种称为守护线程的特殊类型线程。换句话说,守护线程在后台执行任务。这些线程处理那些可能对应用程序有用但即便失败或在操作中途被取消也不会阻碍应用程序的任务。
此外,守护线程无法控制何时终止。一旦所有非守护线程完成,即使此时仍有守护线程在运行,程序也将终止。
守护线程与非守护线程的区别
守护线程 |
非守护线程 |
当只有守护线程运行(或无任何线程运行)时进程将退出。 |
如果至少有一个非守护线程正在运行,则进程不会退出。 |
守护线程用于后台任务。 |
非守护线程用于关键任务。 |
守护线程会突然终止。 |
非守护线程会运行至完成。 |
守护线程可以执行的任务包括:
在 Python 中创建守护线程
要创建一个守护线程,你需要将 Thread 构造函数的 daemon 属性设置为 True。
t1 = threading.Thread(daemon=True)
默认情况下,daemon 属性被设置为 None,如果你将其改为非 None,则 daemon 明确设置了线程是否为守护线程。
示例
以下示例展示了如何创建一个守护线程,并检查该线程是否为守护线程。
import threading
from time import sleep
def run():
thread = threading.current_thread()
print(f'Daemon thread: {thread.daemon}')
thread = threading.Thread(target=run, daemon=True)
thread.start()
print('Is Main Thread is Daemon thread:', threading.current_thread().daemon)
sleep(0.5)
输出:
Daemon thread: True
Is Main Thread is Daemon thread: False
如果在线程对象没有参数的情况下在主线程中创建一个线程对象,则创建的线程将是一个非守护线程,因为主线程不是一个守护线程。因此,在主线程中创建的所有线程默认是非守护线程。但是,我们可以在启动线程之前通过使用 Thread.daemon 属性将 daemon 属性改为 True,即在调用 start() 方法之前。
示例
以下是另一个示例:
import threading
from time import sleep
def run():
thread = threading.current_thread()
print(f'Daemon thread: {thread.daemon}')
thread = threading.Thread(target=run)
thread.daemon = True
thread.start()
print('Is Main Thread is Daemon thread:', threading.current_thread().daemon)
sleep(0.5)
输出:
Daemon thread: True
Is Main Thread is Daemon thread: False
管理守护线程属性
如果你尝试在一个线程启动后设置其守护状态,则会引发 RuntimeError。
示例
以下是一个示例,演示了在尝试设置线程启动后的守护状态时引发的 RuntimeError。
from time import sleep
from threading import current_thread
from threading import Thread
def run():
thread = current_thread()
print(f'Daemon thread: {thread.daemon}')
thread.daemon = True
thread = Thread(target=run)
thread.start()
sleep(0.5)
输出:
Daemon thread: False
Exception in thread Thread-1 (run):
Traceback (most recent call last):
. . . .
. . . .
thread.daemon = True
File "/usr/lib/python3.10/threading.py", line 1203, in daemon
raise RuntimeError("cannot set daemon status of active thread")
RuntimeError: cannot set daemon status of active thread