multiprocessing 模块创建进程
进程创建方法
流程特点
【1】 将需要子进程执行的事件封装为函数
【2】 通过模块的Process类创建进程对象,关联函数
【3】 可以通过进程对象设置进程信息及属性
【4】 通过进程对象调用start启动进程
【5】 通过进程对象调用join回收进程
基本接口使用
Process()
功能 : 创建进程对象
参数 : target 绑定要执行的目标函数
args 元组,用于给target函数位置传参
kwargs 字典,给target函数键值传参
p.start()
功能 : 启动进程
注意:启动进程此时target绑定函数开始执行,该函数作为子进程执行内容,此时进程真正被创建
p.join([timeout])
功能:阻塞等待回收进程
参数:超时时间
注意:
使用multiprocessing创建进程同样是子进程复制父进程空间代码段,父子进程运行互不
影响。
子进程只运行target绑定的函数部分,其余内容均是父进程执行内容。
multiprocessing中父进程往往只用来创建子进程回收子进程,具体事件由子进程完成。
multiprocessing创建的子进程中无法使用标准输入
进程对象属性
p.name 进程名称
p.pid 对应子进程的PID号
p.is_alive() 查看子进程是否在生命周期
p.daemon 设置父子进程的退出关系
如果设置为True则子进程会随父进程的退出而结束
要求必须在start()前设置
如果daemon设置成True 通常就不会使用 join()
自定义进程类
创建步骤
【1】 继承Process类
【2】 重写__init__方法添加自己的属性,使用super()加载父类属性
【3】 重写run()方法
使用方法
【1】 实例化对象
【2】 调用start自动执行run方法
【3】 调用join回收进程
进程池实现
必要性
【1】 进程的创建和销毁过程消耗的资源较多
【2】 当任务量众多,每个任务在很短时间内完成时,需要频繁的创建和销毁进程。此时对计算机压力较大
【3】 进程池技术很好的解决了以上问题。
原理
创建一定数量的进程来处理事件,事件处理完进程不退出而是继续处理其他事件,直到所有事件全都处理完毕统一销毁。增加进程的重复利用,降低资源消耗。
进程池实现
【1】 创建进程池对象,放入适当的进程
from multiprocessing import Pool
Pool(processes)
功能: 创建进程池对象
参数: 指定进程数量,默认根据系统自动判定1
2
3
4
5
【2】 将事件加入进程池队列执行
pool.apply_async(func,args,kwds)
功能: 使用进程池执行 func事件
参数: func 事件函数
args 元组 给func按位置传参
kwds 字典 给func按照键值传参
返回值: 返回函数事件对象1
2
3
4
5
6
【3】 关闭进程池
pool.close()
功能: 关闭进程池1
2
【4】 回收进程池中进程
pool.join()
功能: 回收进程池中进程1
2
进程间通信(IPC)
必要性: 进程间空间独立,资源不共享,此时在需要进程间数据传输时就需要特定的手段进行数据通信。
常用进程间通信方法
管道 消息队列 共享内存 信号 信号量 套接字
消息队列
1.通信原理
在内存中建立队列模型,进程通过队列将消息存入,或者从队列取出完成进程间通信。
实现方法
from multiprocessing import Queue
q = Queue(maxsize=0)
功能: 创建队列对象
参数:最多存放消息个数
返回值:队列对象
q.put(data,[block,timeout])
功能:向队列存入消息
参数:data 要存入的内容
block 设置是否阻塞 False为非阻塞
timeout 超时检测
q.get([block,timeout])
功能:从队列取出消息
参数:block 设置是否阻塞 False为非阻塞
timeout 超时检测
返回值: 返回获取到的内容
q.full() 判断队列是否为满
q.empty() 判断队列是否为空
q.qsize() 获取队列中消息个数
q.close() 关闭队列1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
下为消息队列演示
"""
queue_test.py
消息队列演示
"""
from multiprocessing import Queue,Process
from time import sleep
from random import randint
"""
父进程中创建IO,子进程从父进程中获取IO对象,实际上
他们操作的是同一个IO,属性相互影响
如果在各自进程中创建IO对象,那么这些IO对象互相没有
任何影响
"""
# 创建消息队列
q = Queue(3)
def handle():
while True:
try:
# 获取消息
x,y = q.get(timeout=8)
except Exception as e:
print(e)
break
else:
print("%d+%d=%d"%(x,y,x+y))
def request():
for i in range(6):
sleep(randint(1,16))
x = randint(1,100)
y = randint(1,100)
q.put((x,y)) #存入消息
p1 = Process(target=handle)
p2 = Process(target=request)
p1.start()
p2.start()
p1.join()
p2.join()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
注:上图所示代码通过消息队列将线程p2产生的随机数传给线程p1,并输出它们的和