Python多进程(multiprocessing)
由于Python多线程的弊端和GIL
,适合IO密集型,那么对于计算密集型的应用应该怎么办呢?那就是多进程。(每个进程的GIL
互不影响,多进程来并行编程。)
1. multiprocessing模块
multiprocessing
模块提供了一个Process
类来代表一个进程对象。Processv类描述如下:
multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)`
函数 | 用途 |
---|---|
group |
参数未使用,预留参数,值始终为None |
target |
表示调用对象,即子进程要执行的任务 |
name |
为子进程的名称 |
args |
表示调用对象的位置参数元组,args=(1,2,'egon',) |
kwargs |
表示调用对象的字典,kwargs={'name':'egon','age':18} |
deamon |
为bool 值,表示是否为守护进程 |
- 一些常用的函数
函数 | 用途 |
---|---|
p.start() |
启动进程,并调用该子进程中的p.run() |
p.run() |
进程启动时运行的方法,正是它去调用target 指定的函数,我们自定义类的类中一定要实现该方法 |
p.terminate() |
强制终止进程p ,不会进行任何清理操作,如果p 创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁 |
p.is_alive() |
如果p 仍然运行,返回True |
p.join([timeout]) |
主线程等待p终止(强调:是主线程处于等的状态,而p 是处于运行的状态)。timeout 是可选的超时时间,需要强调的是,p.join 只能join 住start 开启的进程,而不能join 住run 开启的进程 |
- 一些属性
属性 | 用途 |
---|---|
p.daemon |
默认值为False ,如果设为True ,代表p 为后台运行的守护进程,当p 的父进程终止时,p 也随之终止,并且设定为True 后,p 不能创建自己的新进程,必须在p.start() 之前设置 |
p.name |
进程的名称 |
p.pid |
进程的pid |
p.exitcode |
进程在运行时为None 、如果为–N ,表示被信号N 结束(了解即可) |
p.authkey |
进程的身份验证键,默认是由os.urandom() 随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功) |
# 启动子进程
from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
print('Run Subprocess %s (%s)...' % (name, os.getpid()))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('Subprocess will start.')
p.start()
p.join()
print('Subprocess end.')
执行结果如下:
Parent process 4424.
Subprocess will start.
Run Subprocess test (14896)...
Subprocess end.
创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process
实例,用start()
方法启动。join()
方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。
2. 进程池
如果要启动大量的子进程,可以用进程池的方式批量创建子进程:
from multiprocessing import Pool
import os, time, random
def long_time_task(name):
print('Run task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print('Task %s runs %0.2f seconds.' % (name, (end - start)))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Pool(4)
for i in range(4):
p.apply_async(long_time_task, args=(i,))
print('Waiting for all subprocesses done...')
p.close()
p.join()
print('All subprocesses done.')
执行结果如下:
Parent process 15148.
Waiting for all subprocesses done...
Run task 0 (2400)...
Run task 1 (13564)...
Run task 2 (6820)...
Run task 3 (15068)...
Task 1 runs 0.40 seconds.
Task 3 runs 0.78 seconds.
Task 2 runs 1.72 seconds.
Task 0 runs 1.84 seconds.
All subprocesses done.
对Pool对象调用join()
方法会等待所有子进程执行完毕,调用join()
之前必须先调用close()
,调用close()
之后就不能继续添加新的Process
了。
当某个进程fork一个子进程后,该进程必须要调用wait
等待子进程结束发送的sigchld
信号,对子进程进行资源回收等相关工作,否则,子进程会成为僵死进程,被init
收养。所以,在multiprocessing.Process
实例化一个对象之后,该对象有必要调用join
方法,因为在join
方法中完成了对底层wait
的处理。
3. 进程间通信
Process
需要通信,操作系统提供了很多机制来实现进程间的通信。Python的multiprocessing
模块包装了底层的机制,提供了Queue
、Pipes
等多种方式来交换数据。我们以Queue
为例,在父进程中创建两个子进程,一个往Queue
里写数据,一个从Queue
里读数据:
from multiprocessing import Process, Queue
def producer(queue,name,food):
for i in range(2):
print(f'{name}生产了{food}{i}')
res = f'{food}{i}'
queue.put(res) # 通过q.put()来入列,该方法支持存入单个变量,也支持通过列表一次入列多个不同类型的元素
# queue.put(None) # 当生产者结束生产,在队列的最后做一个标志,告诉消费者停止去队列里取数据
def consumer(queue,name):
while True:
res = queue.get() # 通过queue.get()方法来出队列
# if res == None:
# break # 判断队列拿出的是不是生产者放的结束生产的标识,如果是则不取,直接退出,结束程序
print(f'{name}吃了{res}')
if __name__ == '__main__':
queue = Queue() # 父进程创建Queue,并传给各个子进程
producer1 = Process(target=producer,args=(queue,'小明','巧克力'))
consumer1 = Process(target=consumer,args=(queue,'小婷'))
producer1.start() # 启动'写入'子进程producer1
consumer1.start() # 启动'读取'子进程consumer1
producer1.join() # 等待producer1结束
consumer1.terminate() # consumer1进程里是死循环,无法等待其结束,只能强行终止
执行结果如下:
小明生产了巧克力0
小明生产了巧克力1
小婷吃了巧克力0
小婷吃了巧克力1
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具