目录
前言
一、为什么要用多任务?
二、进程是什么?
三、Python 中创建进程的三大步骤
四、主进程与子进程的关系
1. 主进程默认会等待子进程结束
2. 强制等待子进程:join() 方法
3. 获取进程编号:os.getpid() 与 os.getppid()
4. 保护主进程入口:if __name__ == '__main__'
上篇小结
前言
在日常开发中,我们经常会遇到这样的场景:程序需要同时处理多个任务——一边下载文件,一边解析数据,一边更新界面。如果按顺序一个个执行,不仅效率低下,还会让用户等待很久。这时候,多任务编程就成了提升程序性能和用户体验的关键技术。
Python 作为一门易学但功能强大的语言,提供了多种多任务实现方式:进程、线程、协程。其中,进程是操作系统资源分配的最小单位,拥有独立的内存空间,特别适合 CPU 密集型任务,也是理解多任务编程的绝佳起点。
本篇博客将分为上下两篇:
上篇:介绍多任务的基本概念、进程与程序的区别、如何创建和管理子进程,以及主进程与子进程的关系。
下篇:深入讲解进程锁解决资源竞争问题、进程池高效管理大量子进程,以及多进程编程中容易踩的坑。
一、为什么要用多任务?
想象一下:你在用 Python 爬取 1000 个网页,如果一个个顺序执行,每个请求等 1 秒,总耗时将近 17 分钟。而如果让 10 个爬虫“同时”工作,时间就能缩短到 1/10。这就是多任务带来的效率提升。
多任务是指在同一段时间内,程序同时执行多个任务。在 Python 中,实现多任务主要有三种方式:进程、线程、协程。其中,进程是最基础、也是最“独立”的一种方式。
二、进程是什么?
进程就是一个正在运行的程序。当你双击一个应用或者运行python script.py时,操作系统就会创建一个进程。每个进程都有自己独立的内存空间、文件句柄等资源,它们就像一个个独立的“小世界”,互相不干扰。
程序vs进程:程序是硬盘上的静态文件(如
.py文件),进程是程序被加载到内存并执行后的动态实体。主进程:程序启动时默认创建的进程,是整个程序的“根”。
子进程:由主进程或其他子进程通过代码创建的新进程,用于执行特定的子任务。
三、Python 中创建进程的三大步骤
Python 内置的multiprocessing模块让我们能轻松创建和管理进程。
步骤 1:导入模块
import multiprocessing步骤 2:创建进程对象
p = multiprocessing.Process(target=函数名, args=(参数元组,))target:指定子进程要执行的函数名(不要加括号)。args:传给函数的参数,必须是元组,如(1, 'hello');单个参数也要写成(1,)。kwargs:字典形式的关键字参数,如{'name':'张三'}。
步骤 3:启动进程
p.start()基础示例:
import multiprocessing import time def work(name, seconds): for i in range(3): print(f"{name} 正在工作,第 {i+1} 次") time.sleep(seconds) if __name__ == '__main__': p1 = multiprocessing.Process(target=work, args=('进程A', 1)) p2 = multiprocessing.Process(target=work, kwargs={'name': '进程B', 'seconds': 0.5}) p1.start() p2.start()运行后会看到两个进程交替输出,这就是多任务的效果。
四、主进程与子进程的关系
1. 主进程默认会等待子进程结束
如果你在主进程中只写了start(),没有额外设置,主进程会等所有子进程执行完再退出。
2. 强制等待子进程:join()方法
join()会让当前进程(通常是主进程)停下来,直到被调用的子进程执行完毕。
p1.start() p1.join() # 主进程阻塞,直到 p1 结束 print("p1 结束了,主进程继续")如果需要多个子进程按顺序执行,可以这样:
p1.start() p1.join() p2.start() p2.join()3. 获取进程编号:os.getpid()与os.getppid()
有时候我们需要知道当前进程的 ID 或父进程 ID,以便调试或管理。
import os print(f"当前进程 PID:{os.getpid()}") print(f"父进程 PPID:{os.getppid()}")4. 保护主进程入口:if __name__ == '__main__'
在 Windows 系统上,创建子进程时会重新导入主模块,如果没有这个保护,子进程会再次执行创建进程的代码,导致无限递归。强烈建议在所有平台上都加上。
if __name__ == '__main__': p = multiprocessing.Process(target=some_func) p.start()上篇小结
多任务能显著提升程序效率,进程是其中一种实现方式。
每个进程拥有独立的内存空间,互不干扰。
使用
multiprocessing.Process+start()即可创建子进程。join()控制同步等待,os.getpid()获取编号,if __name__ == '__main__'必不可少。
有了这些基础,下篇我们将进一步学习进程锁、进程池以及一些重要注意事项。