进程间的通信(数据交换)
- 现有2个进程A和B,他们都在内存中开辟了空间,那么我们在内存中再开辟一个空间C,作用是连接这两个进程的。对于进程来说内存空间是可以共享的(任何一个进程都可以使用内存,内存当中的空间是用地址来标记的,我们通过查找某一个地址就能找到这个内存)A进程可以不断的向C空间输送东西,B进程可以不断的从C空间读取东西,这就是进程间的通信。
Queue对象
- 对Queue的认识和理解:
- Queue是复杂的数据结构的一种,即队列。
- 队列的特点是“先进先出(FIFO),后进后出(LILO)”
- 与 栈 相反,栈的特点“先进后出,后进先出”
- 使用如下:
- 注意:创建的Queue对象是multiprocessing模块中的Queue类创建的对象。
import multiprocessing
def send(q):
# 发送数据
s_msg = [11, 22, 33]
for i in s_msg:
q.put(i)
print("---已发数据:%s---" % str(i))
print("---数据发送完成---")
def receive(q):
# 接收数据
r_msg = list()
while True:
r_msg.append(q.get())
if q.empty():
break
print("---数据接收完毕:%s---" % str(r_msg))
def main():
# 创建一个队列
# 注意:是multiprocessing模块中的Queue类
q = multiprocessing.Queue()
# 创建Process对象
p1 = multiprocessing.Process(target=send, args=(q,))
p2 = multiprocessing.Process(target=receive, args=(q,))
# 创建、启动进程
p1.start()
p2.start()
if __name__ =="__main__":
main()
管道Pipe
- 管道在信息传输上是以流的方式传输, 也就是你从A进程不断的写入,B进程源源不断的读出,A进程先写入的就会被B进程先读出,后写进来的就会被后读出。
- 管道本质:
- 在内存中开辟一个新的空间,对多个进程可见,在通信形式上形成一种约束。
- 创建管道:
- 导入multiprocessing模块中的 管道方法:Pipe(duplex)方法
- 参数:duplex默认值为True,表示管道为双向管道(全双工)如果设置为False则为单项管道(半双工)
- 返回值:返回两个管道流对象,两个管道流对象分别表示管道的两端。
- 如果参数为True的时候,两个对象均可发送接收,
- 如果为False时,则第一个对象只能接收,第二个就只能发送。
- 创建管道对象,管道方法返回两个对象。
- 利用send()方法、recv()方法向管道发送、接收数据。
- 一次recv()只能接收一次send()的内容。
- send()方法:
- 数据往管道里面送
- send可以发送的数据类型比较多样,字符串,数字,列表
- recv()方法:
- 从管道中接收数据
- recv()函数为阻塞函数,当管道中数据为空的时候会阻塞
from multiprocessing import Process, Pipe
def text(name, child_conn):
print(name + ":开始执行...")
print("--执行完成--" )
# 向管道发送数据
child_conn.send(name + "--OK--")
if __name__ == "__main__":
job = []
# 使用全双工通信管道(Pipe()中duplex参数默认值为True)
# 创建管道对象
# Pipe() 该方法的返回值为两个管道对象
child_conn, parent_conn = Pipe()
for i in range(5):
p = Process(target=text, args=(str(i+1), child_conn))
job.append(p)
p.start()
# 从管道接收数据
# 若管道中数据为空时发生阻塞
for i in range(5):
print(parent_conn.recv())
共享内存Value、Array
- Value、Array是通过共享内存的方式共享数据
Manager对象
- Manager是通过共享进程的方式共享数据。
- Manager()返回的manager对象控制了一个server进程,此进程包含的python对象可以被其他的进程通过proxies来访问。从而达到多进程间数据通信且安全。
- Manager对象控制一个拥有list、dict、Lock、Condition、Event、Queue等对象的服务端进程,并且允许其他进程访问这些对象。
import multiprocessing
from random import randint
def text(d, key, value):
d[key] = value
if __name__ == "__main__":
mgr = multiprocessing.Manager()
d = mgr.dict()
jobs = [multiprocessing.Process(target=text, args=(d, i+1, (i+1)**2)) for i in range(5)]
for j in jobs:
j.start()
for j in jobs:
j.join()
print(dict(d))
print("--- end ---")