8. 多进程开发
进程是计算机中资源分配的最小单元;一个进程中可以有多个线程,同一个进程中的线程共享资源。
进程与进程之间是相互独立的,进程之间的数据不共享。
python 中通过多进程可以利用CPU的多核优势,计算密集型操作适用于多进程开发。
进程创建
python
import multiprocessing
def task():
pass
if __name__ == "__main__":
p = multiprocessing.Process(target=task)
p.start()fork
在类 Unix 系统中,fork 是创建新进程的常用方法。fork 会拷贝当前进程的几乎所有资源到新进程中,包括打开的文件描述符、内存空间等。
支持文件对象/线程锁等传参。
拷贝主进程到新创建的子进程中。
python
import multiprocessing
import time
def task():
print("子进程前", name)
name.append(123)
print("子进程后", name)
if __name__ == "__main__":
multiprocessing.set_start_method("fork")
name = []
p1 = multiprocessing.Process(target=task)
p1.start()
time.sleep(1)
print("主进程", name) # 主进程的name没有被子进程修改
# 输出结果:
# 子进程前 []
# 子进程后 [123]
# 主进程 []spawn 和 forkserver
在 unix, windows 使用 spawn 创建进程时,他不会完全拷贝主进程的资源例如(fork),他会将必备的资源通过传参将需要的资源传递给子进程。
在部分 unix 系统中,forkserver 会先启动一个“干净”的 server 进程由其 fork 出子进程(子进程的父进程为 server),随后主进程与子进程通过管道等 IPC 直接通信。
不支持文件对象/线程锁等传参。
python
import multiprocessing
import time
def task(name):
print("子进程前", name)
name.append(123)
print("子进程后", name)
if __name__ == "__main__":
multiprocessing.set_start_method("spawn")
name = []
p1 = multiprocessing.Process(target=task, args=(name,))
p1.start()
time.sleep(1)
print("主进程", name) # 主进程的name没有被子进程修改进程常见方法
start()
当前进程准备就绪,等待被 CPU 调度(工作单元其实是进程中的线程)
join()
join(timeout=None) 阻塞当前进程,等待子进程结束,timeout 可设置等待时间
daemon
p.daemon = 布尔值:设置守护进程,必须放在start之前
- p.daemon = True 设置为守护进程,主进程结束,守护进程也会结束
- p.daemon = False 设置为非守护进程,主进程等待子进程,子进程执行完毕后,主进程才结束。
进程名称设置和获取
python
import multiprocessing
import os
import threading
import time
def task(arg):
# 获取当前进程id,和父进程id
print("进程id:", os.getpid(), "父进程id:", os.getppid())
# 获取线程个数
print("线程个数:", len(threading.enumerate()))
time.sleep(2)
# 获取进程名称
print("当前进程的名称:", multiprocessing.current_process().name)
if __name__ == "__main__":
multiprocessing.set_start_method("spawn")
p = multiprocessing.Process(target=task, args=("xxx",))
# 设置进程名称
p.name = "哈哈哈哈"
p.start()
print("继续执行")自定义进程类
直接将线程需要做的事写到 run 方法中
python
import multiprocessing
class MyProcess(multprocessing.Process):
def run(self):
print("执行此进程", self.args)
if __name__ == "__main__":
multiprocessing.set_start_method("spawn")
p = MyProcess(args=("xxx",))
p.start()
print("继续执行")cpu_count()
计算cpu个数, 程序中一般 CPU 多少个,就创建多少个进程
python
import multiprocessing
def task(args):
print("进程运行")
if __name__ == "__main__":
count = multiprocessing.cpu_count()
print("CPU个数:", count)
# 因为主进程占一个
for i in range(count - 1):
p = multiprocessing.Process(target=task, args=("xxx",))
p.start()