进程间的通信
★管道
Python中的管道有两种工作方式:
1,单项(半双工)
一端只能发送数据,另一端只能接收数据。
2,双向(全双工)
两端都既能发送数据又能接收数据,一端发送的数据只能由另一端接收。
标准库模块multiprocessing中提供了一个函数Pipe(),其返回值是一个元组,元组中包含两个对象,
分别表示管道两端的连接。
调用函数Pipe()时,如果不传入参数或传入参数为True,管道的工作方式为双向(全双工);
如果传入的参数为False,管道的工作方式为单向(半双工),其中,对于返回的元组,第一个
连接对象只能接收数据,第二个连接对象只能发送数据。
对于管道两端的连接对象,主要由两个方法:
1,send(self,obj)
用于将参数obj指定的对象发送到管道。
2,recv(self)
用于从管道中接收对象。
1 from multiprocessing import Pipe 2 3 #conn1和conn2为管道的两端。 4 conn1, conn2 = Pipe() #Pipe()或Pipe(True)为全双工 5 6 conn1.send('conn1第1次发送的数据') 7 conn1.send('conn1第2次发送的数据') 8 9 conn2.send('conn2第1次发送的数据') 10 conn2.send('conn2第2次发送的数据') 11 12 print(conn1.recv()) 13 print(conn1.recv()) 14 15 print(conn2.recv()) 16 print(conn2.recv()) 17 18 19 #测试半双工 20 c1, c2 = Pipe(False) #Pipe(False)为半双工。c1只能接收,c2只能发送。 21 22 c2.send('c2发送的数据') 23 print(c1.recv()) 24 25 # c1.send('c1发送的数据') #OSError: connection is read-only
#【1】进程间的通信之管道
管道是实现进程间通信的常见方式之一。
1 from multiprocessing import Process, Pipe 2 import os, time, random 3 4 #发送数据的子进程执行 5 def send_data(conn): 6 print('发送数据的子进程%d启动' % os.getpid()) 7 8 for obj in list(range(1, 10)): 9 print('发送数据:%s' % obj) 10 conn.send(obj) 11 time.sleep(random.random() * 3) 12 13 print('发送数据:None') 14 conn.send(None) 15 16 print('发送数据的子进程%d结束' % os.getpid()) 17 18 #接收数据的子进程执行 19 def recv_data(conn): 20 print('接收数据的子进程%d启动' % os.getpid()) 21 22 while True: 23 item = conn.recv() 24 if item is None: 25 print('接收数据:None') 26 break 27 print('接收数据:%s' % item) 28 time.sleep(random.random() * 3) 29 30 print('接收数据的子进程%d结束' % os.getpid()) 31 32 print('父进程%d启动' % os.getpid()) 33 34 cr, cs = Pipe(False) #半双工 35 36 ps = Process(target=send_data, args=(cs,)) #args指定target接收的参数。 37 pr = Process(target=recv_data, args=(cr,)) 38 39 ps.start() 40 pr.start() 41 42 #两个子进程阻塞父进程 43 ps.join() 44 pr.join() 45 46 print('父进程%d结束' % os.getpid())
1 from multiprocessing import Process, Pipe 2 3 def f(conn): 4 conn.send([1, {"name":"Li"}, 'hi']) 5 response=conn.recv() 6 print("response",response) 7 conn.close() 8 print("c_conn传入子进程后的id:",id(conn)) 9 10 if __name__ == '__main__': 11 12 p_conn, c_conn = Pipe() #全双工 13 print("c_conn在主进程中的id:",id(c_conn)) 14 p = Process(target=f, args=(c_conn,)) 15 p.start() 16 print(p_conn.recv()) 17 p_conn.send("hello!") 18 p.join()
#【2】进程间的通信之Manager
如果想要实现进程间的通信,Manager也是常见的实现方式之一。
与共享内存相比,Manager更加灵活,因为它可以支持多种对象类型。此外,Manager还可以通过网络
被不同的计算机上的进程所共享。但是,Manager的速度比共享内存慢。
1 from multiprocessing import Process, Manager 2 3 #子进程执行操作 4 def f(d,l): 5 d[1] = 18 6 d['2'] = 56 7 l.reverse() #列表反转 8 if __name__ == '__main__': 9 manager = Manager() 10 11 #通过Manager创建一个用于进程间通信的字典 12 d = manager.dict() 13 #通过Manager创建一个用于进程间通信的列表 14 l = manager.list(range(5)) 15 16 p = Process(target=f,args=(d,l,)) 17 p.start() 18 p.join() #阻塞父进程 19 20 print(d) 21 print(l)
#【3】进程间的通信之共享内存
参考:另一篇博客。
#【4】进程间的通信之进程队列(multiprocessing.Queue())
1 #import queue 2 #import time 3 import multiprocessing 4 q = multiprocessing.Queue() 5 6 7 def foo(q, n): 8 q.put(1) 9 q.put(2) 10 print("子进程:", id(q)) 11 12 13 if __name__ == '__main__': 14 #q=queue.Queue() #<--错误;这个为线程队列,不能在进程间共享队列元素。 15 procList = [] 16 print("主进程:", id(q)) 17 for i in range(2): 18 p = multiprocessing.Process(target=foo, args=(q, i))#此处用进程队列。 19 p.start() 20 procList.append(p) 21 #q.start() 22 for p in procList:#阻塞主進程 23 p.join() 24 #time.sleep(5) 25 print(q.get()) 26 print(q.get())
------山的那一边

浙公网安备 33010602011771号