进程间是无法随意通信的,但有时候我们也需要多个进程间通信,其实操作系统也为我们提供了几种机制来实现进程间的通信;比如说:队列( queue )、管道( pipe )、进程管理器( manager )、信号量等。下面重点介绍一下队列( queue )、管道( pipe )、进程管理器( manager )。
1.Queue ( 队列 )
我们可以使用multiprocessing模块中的Queue(队列)来完成多进程间的数据传递,我们可以通过queue获取队列对象。
队列先进先出,后进后出,和我们日常生活中的排队一样
1.1 queue的常见方法
put(item, block=True, timeout=None): 往队列里放数据。如果满了的话,blocking = False 直接报 Full异常。如果blocking = True,就是等一会,timeout必须为 0 或正数。None为一直等下去,0为不等,正数n为等待n秒还不能存入,报Full异常。
get(item, block=True, timeout=None): 从队列里取数据。如果为空的话,blocking = False 直接报 empty异常。如果blocking = True,就是等一会,timeout必须为 0 或正数。None为一直等下去,0为不等,正数n为等待n秒还不能读取,报empty异常。
其他的请看下面程序:
import queue
# Queue 先进先出 LifeQueue先进后出 后进先出
# print(dir(queue))
# Queue() 可以填入参数 确定有多少;若不填参数 随便填 填多少算多少 这里设置队列长度为3
q = queue.Queue(3)
# q.put() 将一个值放入队列中
q.put("a")
q.put("b")
q.put("c")
# 确定队列的长度
print(q.qsize())
# 判断是否为空,为空返回True,不为空返回False
print(q.empty())
# 判断队列是否满队,如果满队返回True,如果不满队返回False
print(q.full())
# 从队列获取一个数据,获取的数据是队列里传入的时间最长的那个
print(q.get())
print(q.get())
print(q.get())
print(q.qsize())
输出结果为:
3
False
False
a
b
c
0
1.2 当队列长度小于串如数据数目是会阻断进程,比如说:
q = queue.Queue(3)
q.put("a")
q.put("b")
q.put("c")
q.put("d")
# 确定大小
print(q.qsize())
# 判断是否为空
print(q.empty())
# 判断是否不为空
print(q.full())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.qsize())
运行时不会发现,不会输出任何结果,而且程序也不报错。
1.3 put里的timeout
q = queue.Queue(3)
q.put("a")
q.put("a")
q.put("a")
print(q.qsize())
# 判断是否为空
print(q.empty())
# 判断是否不为空
print(q.full())
print(q.get())
print(q.get())
print(q.get())
q.put("a", block=True, timeout=3)
print(q.qsize())
运行结果如下:
3
False
True
a
a
a
1
1.4 实现进程间的数据传递
from multiprocessing import Process, Pipe
def sendMsg(p):
msg = "这个是利用管道传输的数据"
print("一个独立子进程开始传输数据了,数据是:", msg)
p.send(msg)
print("数据发送成功")
p.close()
def receiveMsg(p):
print("接受到管道传输的数据:", p.recv())
if __name__ == '__main__':
print("------------start----------------")
# pipe = Pipe()
(parentPipe, sonPipe) = Pipe()
# print(parentPipe, sonPipe)
task1 = Process(target=sendMsg, args=[parentPipe])
task1.start()
task2 = Process(target=receiveMsg, args=[sonPipe])
task2.start()
print("------------end----------------")
运行结果如下:
------------start----------------
------------end----------------
一个独立子进程开始传输数据了,数据是: 这个是利用管道传输的数据
数据发送成功
接受到管道传输的数据: 这个是利用管道传输的数据
2. pipe管道
from multiprocessing import Pipe, Process
def send_msg(p):
msg = "这个是用管道传输的数据"
print("一个独立子进程开始数据了,数据是:", msg)
p.send(msg)# 发送数据
p.close()# 关闭管道
def receive_msg(p):
print("接收到管道传输的数据是:", p.recv())# p.recv()接受数据
if __name__ == '__main__':
print("-----------start-------------")
(per_pipe, son_pipe) = Pipe()
# print(Pipe())
t1 = Process(target=send_msg, args=[per_pipe])
t1.start()
t2 = Process(target=receive_msg, args=[son_pipe])
t2.start()
print("------------end---------------")
运行结果为:
-----------start-------------
------------end---------------
一个独立子进程开始数据了,数据是: 这个是用管道传输的数据
接收到管道传输的数据是: 这个是用管道传输的数据
3. 设备管理器( Manager )
def save_data(l, d):
l.append("高要")
l.append("赵本山")
l.append("刘亦菲")
d["name"] = "武松"
d["age"] = "潘金莲"
d["nickname"] = "西门庆"
print(l)
print(d)
# manger里面的进程是守护进程
if __name__ == '__main__':
print("----------start------------")
# manager = Manager()
# lists = manager.list()
# dicts = manager.dict()
with Manager() as manager:
lists = manager.list()
dicts = manager.dict()
ls = []
# 在以一个循环里进程的创建
for x in range(5):
t1 = Process(target=save_data, args=[lists, dicts])
t1.start()
ls.append(t1)
for x in ls:
x.join()
print("-----------end-------------")
运行结果是:
----------start------------
['高要', '赵本山', '刘亦菲']
{'name': '武松', 'age': '潘金莲', 'nickname': '西门庆'}
['高要', '赵本山', '刘亦菲', '高要', '赵本山', '刘亦菲']
{'name': '武松', 'age': '潘金莲', 'nickname': '西门庆'}
['高要', '赵本山', '刘亦菲', '高要', '赵本山', '刘亦菲', '高要', '赵本山', '刘亦菲']
{'name': '武松', 'age': '潘金莲', 'nickname': '西门庆'}
['高要', '赵本山', '刘亦菲', '高要', '赵本山', '刘亦菲', '高要', '赵本山', '刘亦菲', '高要', '赵本山', '刘亦菲']
{'name': '武松', 'age': '潘金莲', 'nickname': '西门庆'}
['高要', '赵本山', '刘亦菲', '高要', '赵本山', '刘亦菲', '高要', '赵本山', '刘亦菲', '高要', '赵本山', '刘亦菲', '高要', '赵本山', '刘亦菲']
{'name': '武松', 'age': '潘金莲', 'nickname': '西门庆'}