day9-进程间数据交互及共享
进程间数据通信的实现方法
2.Pipe()
Pipe()函数返回一对由管道连接的连接对象,代表了pipe的两端,默认情况下为双工(双向),每个对象都有send()和recv()方法。
from multiprocessing import Process, Pipe def f(conn): conn.send([42, None, 'hello']) #发送数据 print(conn.recv()) #接收数据 conn.close() if __name__ == '__main__': # 生成一个管道对象 parent_conn, child_conn = Pipe() #包含2个返回对象(父连接,子连接) p = Process(target=f, args=(child_conn,)) #生成一个子进程对象 p.start() #启动子进程 print(parent_conn.recv()) #在主进程的父连接接收数据 parent_conn.send("hello world") 发送数据 p.join() #运行输出 [42, None, 'hello'] hello world
区别和小结
pipe用来在两个进程间通信。queue用来在多个进程间实现通信。此两种方法为所有系统多进程通信的基本方法。
以上2个方法通过实现对进程间的数据传递,而不是共享,如果实现和多线程一样对同一份数据进行共享,可以使用下面的方法
共享
Manager()方法返回一个manager对象控制一个服务器进程,该进程持有Python对象,并允许其他进程使用代理来对他们进行操作。
Manager()方法返回的manager将支持的类型:list,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaphore,Condition,Event,Barrier,Queue,Value 和Array。
from multiprocessing import Process, Manager import os def f(d, l): d[os.getpid()] = os.getpid() l.append(os.getpid()) print(l) if __name__ == '__main__': with Manager() as manager: d = manager.dict() #生成可在多个进程间传递和共享的dict l = manager.list(range(5)) #生成可在多个进程间传递和共享的list p_list = [] #存放进程对象的列表 for i in range(10): #启动10个进程 p = Process(target=f, args=(d, l)) p.start() p_list.append(p) for res in p_list: #等待进程执行结果 res.join() print(d) print(l) #运行输出 [0, 1, 2, 3, 4, 22107] [0, 1, 2, 3, 4, 22107, 22109] [0, 1, 2, 3, 4, 22107, 22109, 22108] [0, 1, 2, 3, 4, 22107, 22109, 22108, 22110] [0, 1, 2, 3, 4, 22107, 22109, 22108, 22110, 22111] [0, 1, 2, 3, 4, 22107, 22109, 22108, 22110, 22111, 22112] [0, 1, 2, 3, 4, 22107, 22109, 22108, 22110, 22111, 22112, 22113] [0, 1, 2, 3, 4, 22107, 22109, 22108, 22110, 22111, 22112, 22113, 22114] [0, 1, 2, 3, 4, 22107, 22109, 22108, 22110, 22111, 22112, 22113, 22114, 22115] [0, 1, 2, 3, 4, 22107, 22109, 22108, 22110, 22111, 22112, 22113, 22114, 22115, 22116] {22112: 22112, 22113: 22113, 22114: 22114, 22115: 22115, 22116: 22116, 22107: 22107, 22108: 22108, 22109: 22109, 22110: 22110, 22111: 22111} [0, 1, 2, 3, 4, 22107, 22109, 22108, 22110, 22111, 22112, 22113, 22114, 22115, 22116] Process finished with exit code 0
解析:这里不像线程在对同一份数据操作是需要加锁,manager()方法内部默认已经加锁了。