python多进程(二)
代码地址:https://github.com/FLBa9762/Mutli_Process.git
Queue队列实现多进程的通信(demo5.py)
创建Queue队列
创建了一个长度为3的队列,最多可以存放三个数据
from multiprocessing import Queue
QUE = Queue(3)
添加数据
使用Queue类的put()方法
QUE.put("message1")
获取数据
使用Queue类的get()方法, 先放先取
QUE.get()
判断队列是满还是空
返回值为bool类型
QUE.full()
QUE.empty()
一个进程通信例子
此例子中,接收进程会一直等待发送进程发送给Queue数据
注:没有添加接收进程的停止判断
from multiprocessing import Queue
import multiprocessing
import numpy as np
import time
def episode(q):
data = np.arange(1, 11)
for i in data:
q.put(i)
def send_message(q):
for epi in range(10):
print("episode: {}".format(epi))
episode(q)
time.sleep(3)
print("send_done! ")
def receive_message(q):
receiver = []
i = 0
while True:
rec = q.get()
receiver.append(rec)
print("receive: {}".format(i))
i += 1
def run():
q = Queue(20)
print(q.qsize())
process1 = multiprocessing.Process(target=send_message, args=(q,))
process2 = multiprocessing.Process(target=receive_message, args=(q,))
process1.start()
# process1.join()
process2.start()
if __name__ == '__main__':
run()
进程池Pool(demo6.py)
设置进程池最大数量
设置最大进程数为3,但是还未创建,在使用时候创建
from multiprocessing import Pool
po = Pool(processes=3)
进程池添加任务
用Pool类的apply_async()方法, send_message是任务函数对象,(i,)是send_message()元组形式的参数
po.apply_async(send_message, (i,))
进程池管理
Pool进程池使用时需要手动添加一些管理,否则不能顺利执行完所有任务
po.close() # 关闭进程池,使其不接收新的任务
po.join() # 等待进程池里的任务结束,主进程再退出
python为进程池设置了使用规则,进程池创建完成、分配好任务之后,需要执行po.close()手动关闭进程池才能正常运行,如果不关闭就会报错
Traceback (most recent call last):
File "C:/Users/fusion007/Desktop/Mutli_Process-main/demo6.py", line 36, in <module>
po.join() # 等待进程池里的任务结束,主进程再退出
File "D:\Anaconda3\lib\multiprocessing\pool.py", line 553, in join
raise ValueError("Pool is still running")
ValueError: Pool is still running
po.join()的用法和之前的Process.join()相近,就是让主进程等待进程池任务结束后再退出。
Pool进程池例子
from multiprocessing import Pool
import time
import os
import random
def send_message(msg):
t_start = time.time()
print("{} 开始执行,进程编号为 {}".format(msg, os.getpid()))
# time.sleep(0.11)
time.sleep(random.random()*2)
t_stop = time.time()
print('{} 执行完毕, 用时 {} '.format(msg, t_stop - t_start))
if __name__ == '__main__':
po = Pool(processes=3)
for i in range(0, 10):
po.apply_async(send_message, (i,))
print("----------start------------ {}".format(os.getpid()))
# po.close() # 关闭进程池,使其不接收新的任务
po.join() # 等待进程池里的任务结束,主进程再退出
print("-----------end-------------")
Pipe管道使用(demo7.py)
创建一个Pipe管道
创建管道连接, 设置参数 duplex 为True表示管道是全双工模式的,返回值 conn_1 和 conn_2 分别是管道的两端。
import multiprocessing
conn_1, conn_2 = multiprocessing.Pipe(duplex=True)
为进程分配使用的管道
将管道两端作为参数传入进程的任务中,再从任务中执行收、发等工作
p1 = multiprocessing.Process(target=send_message, args=(conn_1,))
p2 = multiprocessing.Process(target=receive_message, args=(conn_2,))
p1.start()
p2.start()
p1.join()
p2.join()
p1 和 p2 两个进程的任务 send_message 和 receive_message 的代码如下:
def send_message(conn_1):
conn_1.send("send_message!!!")
print("conn1 send message: {}".format("send_message!!!"))
data = conn_1.recv()
print("ok, finish ! {}".format(data))
def receive_message(conn2):
data = conn2.recv()
print("conn2 receive data: {}".format(data))
conn2.send("conn2 received message")
print("conn2 send message:{}".format("conn2 received message"))
实验中,recv( ) 函数在执行时要等待另一个端口发送来信息才可以,否则会一直等待
关闭管道的端口
管道的 close() 函数
conn2.close()
结果
conn1发送——> conn2接受,并回复——>conn1受到回复,结束
D:\Anaconda3\python.exe C:/Users/fusion007/Desktop/Mutli_Process-main/demo8.py
conn1 send message: send_message!!!
conn2 receive data: send_message!!!
conn2 send message:conn2 received message
ok, finish ! conn2 received message