Python守护进程与守护线程的行为机制及并行控制

苏见山
苏见山
发布时间:2026-10-11| 3人浏览过
原创

本文深入解析Python中守护进程(Daemon Process)与守护线程(Daemon Thread)的核心行为机制。重点阐述守护进程在主进程代码结束后立即终止且无法开启子进程的限制,以及守护线程随主线程非守护线程结束而销毁的特性。通过对比守护与非守护进程/线程的并行执行顺序、内存共享及阻塞行为,提供清晰的代码示例与操作指南,帮助开发者掌握并发编程中的资源管理与生命周期控制。

守护进程的核心行为与限制

在Python的多进程编程中,守护进程(Daemon Process)的生命周期严格依赖于主进程。其核心行为特征如下:

  • 生命周期绑定:守护进程会在主进程代码执行结束后立即终止,无论其自身任务是否完成。
  • 子进程限制:守护进程内部无法再开启子进程,否则程序会抛出 AssertionError。
  • 内存开销:子进程开辟内存空间需要耗费时间,因此在设计时需权衡守护与非守护进程的使用。

代码实现与注意事项

以下示例展示了如何创建一个守护进程。关键步骤是在调用 start() 之前设置 daemon = True。

from multiprocessing import Process
import os, time, random

def task():
    print('%s is running' % os.getpid())
    time.sleep(2)
    print('%s is done' % os.getpid())

    # 注意:守护进程内无法再开启子进程,否则抛出异常
    # p = Process(target=time.sleep, args=(3,))
    # p.start()

if __name__ == '__main__':
    p = Process(target=task)
    p.daemon = True  # 必须在 p.start() 之前设置
    p.start()
    print('主')

若在主进程中使用 p.join(),主进程会阻塞等待子进程结束。但由于守护进程随主进程代码结束而终止,join() 的行为可能受到主进程退出逻辑的影响。通常情况下,主进程代码执行完毕即触发守护进程的回收。

if __name__ == '__main__':
    p = Process(target=task)
    p.daemon = True  # 必须在 p.start() 之前设置
    p.start()
    p.join()
    print('主')

守护进程与非守护进程的并行控制

当守护子进程与非守护子进程并存时,主进程的执行顺序与进程调度密切相关。主进程代码运行结束后,守护进程随即终止,而非守护进程则继续运行直至完成。

混合进程示例

以下代码演示了守护进程(p1)与非守护进程(p2)的并行执行。主进程打印“main-------”后,守护进程 p1 会随主进程逻辑结束而可能被终止,而非守护进程 p2 会独立运行。

from multiprocessing import Process
from threading import Thread
import time, os

def foo():
    print(123)
    time.sleep(1)
    print("end123")

def bar():
    print(456)
    time.sleep(3)
    print("end456")

if __name__ == '__main__':
    p1 = Process(target=foo)
    p2 = Process(target=bar)
    p1.daemon = True
    p1.start()
    p2.start()
    print("main-------")

守护线程的生命周期与内存共享

守护线程(Daemon Thread)的行为与守护进程类似,但其生命周期依赖于主线程。守护线程等待主线程运行完毕后被销毁。需要注意的是,“运行完毕”并非指线程终止运行,而是指主线程所在进程内所有非守护线程运行完毕。

守护线程示例

以下示例展示了如何创建守护线程。同样,必须在 start() 之前设置 daemon = True。

from multiprocessing import Process
from threading import Thread
import os, time, random

def task():
    # 注意:守护进程内无法再开启子进程,否则抛出异常
    # t = Thread(target=time.sleep, args=(3,))
    # t.start()
    print('%s is running' % os.getpid())
    time.sleep(2)
    print('%s is done' % os.getpid())

if __name__ == '__main__':
    t = Thread(target=task)
    t.daemon = True
    t.start()
    print('主')

混合线程示例

当守护子线程与非守护子进程并存时,它们共享内存空间。主线程执行完毕前,守护线程可能执行后续代码。主线程运行完毕的定义是所有非守护线程统统运行完毕。

from threading import Thread
import time

def foo():
    print(123)
    time.sleep(1)
    print("end123")

def bar():
    print(456)
    time.sleep(3)
    print("end456")

if __name__ == '__main__':
    t1 = Thread(target=foo)
    t2 = Thread(target=bar)

    t1.daemon = True

    t2.start()
    t1.start()
    print("main-------")

总结

掌握守护进程与守护线程的行为机制,对于编写高效、稳定的Python并发程序至关重要。守护进程随主进程代码结束而终止,且无法开启子进程;守护线程随主线程非守护线程结束而销毁。在实际开发中,应根据业务需求合理选择守护与非守护进程/线程,并注意内存共享与阻塞行为的影响。

以上就是Python实现守护进程、守护线程、守护非守护并行的详细内容,更多关于Python并发编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。