由于进程空间相对独立,资源无法共享,基于这种情况,就需要使用一些方法使得不同的进程之间可以进行通信。
我这里介绍三种进程间通信的方式:管道、消息队列、共享内存。
管道的通信原理:
代码实现:
from multiprocessing import Process,Pipe
#创建管道对象
fd1,fd2 = Pipe(duplex = False)
def test(msg):
#向管道写入内容
fd2.send(msg)
jobs = []
for i in range(5):
msg = "No." + str(i)
p = Process(target = test, args = (msg,))
jobs.append(p)
p.start()
for i in range(5):
#读取管道
data = fd1.recv()
print(data)
# 回收进程
for i in jobs:
i.join()
其中:
fd1, fd2 = Pipe(duplex = True)
fd.send(data)
fd.recv()
运行结果:
gk@gk-vm:~/python/process_communication$ python3 pipe_test.py
No.0
No.1
No.3
No.4
No.2
观察读取的内容,会发现读取的顺序是不一定的。我们是有序的将内容放入管道的,但是取出来的数据确实无序的,说明管道的读取不是按照顺序读取的。
消息队列的通信原理:
代码实现:
from multiprocessing import Process,Queue
import time
#创建消息队列
q = Queue(maxsize=3)
# 向队列中放入数据
def test1():
time.sleep(3)
q.put("数据1")
q.put("数据2")
# 从队列中取出数据
def test2():
time.sleep(1)
# block=True,timeout=5表示如果队列为空则阻塞等待五秒,如果五秒后队列中依然为空,就会停止阻塞,抛出queue.Empty异常,比如把这里的timeout改为1秒,就会抛出异常
print("收到消息:", q.get(block=True, timeout=5))
p1 = Process(target = test1)
p2 = Process(target = test2)
p1.start()
p2.start()
p1.join()
p2.join()
# 队列是否已满
print("q.full():", q.full())
# 队列是否为空
print("q.empty():", q.empty())
# 队列中消息数量
print("q.qsize():", q.qsize())
# 关闭队列
q.close()
# 在队列关闭后尝试获取数据
try:
print(q.get())
except OSError as e:
print("消息队列已关闭")
print("error:", e)
其中:
q = Queue(maxsize = 3)
q.put(data, [block, timeout])
data = q.get([block, timeout])
q.full()
q.empty()
q.qsize()
q.close()
运行结果:
gk@gk-vm:~/python/process_communication$ python3 queue_test2.py
收到消息: 数据1
q.full(): False
q.empty(): False
q.qsize(): 1
消息队列已关闭
error: handle is closed
共享内存的通信原理:
代码实现:
from multiprocessing import Process, Value
import random
#创建共享内存
num = Value('i', 100)
# 操作共享内存增加
def num_add():
for i in range(10):
# 对value属性操作即操作共享内存数据
num.value += random.randint(1,10)
# 操作共享内存减少
def num_reduce():
for i in range(10):
num.value -= random.randint(1,10)
p1 = Process(target = num_add)
p2 = Process(target = num_reduce)
p1.start()
p2.start()
p1.join()
p2.join()
print("result:", num.value)
其中:
obj = Value(ctype, obj)
obj.value:共享内存值,对其修改即修改共享内存
多次运行结果:
gk@gk-vm:~/python/process_communication$ python3 value_test.py
result: 90
gk@gk-vm:~/python/process_communication$ python3 value_test.py
result: 84
gk@gk-vm:~/python/process_communication$ python3 value_test.py
result: 108
gk@gk-vm:~/python/process_communication$ python3 value_test.py
result: 112
gk@gk-vm:~/python/process_communication$ python3 value_test.py
result: 98
另外:
另外一种开辟共享内存空间的方法:
obj = Array(ctype, obj)
实现代码:
from multiprocessing import Process,Array
import time
# 创建共享内存,初始放入列表
test = Array('i',[1,2,3])
# 创建共享内存,开辟9个整形空间
# test = Array('i',9)
# 存入字符串,要求bytes格式
# test = Array('c',b'abcdef')
def test1():
test[0] = 9
def test2():
test[1] = 8
p1 = Process(target = test1)
p2 = Process(target = test2)
p1.start()
p2.start()
p1.join()
p2.join()
for i in test:
print(i)
运行结果:
gk@gk-vm:~/python/process_communication$ python3 value_array_test.py
9
8
3
管道 | 消息队列 | 共享内存 | |
---|---|---|---|
开辟空间 | 内存 | 内存 | 内存 |
读写方式 | 两端读写(单/双向) | 先进先出 | 覆盖之前内容 |
效率 | 一般 | 一般 | 较高 |
应用 | 多用于父子进程 | 广泛灵活 | 需要注意进行互斥操作 |