02-进程通信
进程通信有两种方式,分别是队列和管道
队列通信
import time
from multiprocessing import Process, Queue
def func(q):
time.sleep(1)
q.put([1, 'yaowy', 28])
if __name__ == '__main__':
q = Queue()
p = Process(target=func, args=(q,))
p.start()
print(q.get())
print(q.get())

Queue.get() 会阻塞。
管道通信
import time
from multiprocessing import Process, Pipe
def func(pipe):
time.sleep(1)
pipe.send([1, 'yaowy', 28])
if __name__ == '__main__':
pipel, piper = Pipe()
p = Process(target=func, args=(pipel,))
p.start()
print(piper.recv())
print(piper.recv())

Pipe.recv 也会形成阻塞效果。Pipe 是双向的,会返回两个对象,表示管道的两端,recv 方法和 send 方法是相互的。
进程同步
import time
from multiprocessing import Process, Lock
def func(l: Lock, i):
l.acquire()
try:
print('-'*10, i)
time.sleep(1)
finally:
print('+'*10, i)
l.release()
if __name__ == '__main__':
lock = Lock()
for num in range(5):
Process(target=func, args=(lock, num)).start()

进程同步和线程同步一样使用方便。
进程中共享状态
共享内存
from multiprocessing import Process, Value, Array
def func(v: Value, a: Array):
v.value = 3.1415926
for i in range(len(a)):
a[i] = -a[i]
if __name__ == '__main__':
v = Value('d', 0.0)
a = Array('i', range(10))
p = Process(target=func, args=(v, a))
p.start()
p.join()
print(v.value)
print(a[:])

p.join() 是必须的,它会让主进程等待子进程执行完。
不过这个方法共享内存并不是最方便的
服务进程
由 Manager() 返回的管理器对象控制一个服务进程,该进程保存Python对象并允许其他进程使用代理操作它们。
Manager() 返回的管理器支持类型: list 、 dict 、 Namespace 、 Lock 、 RLock 、 Semaphore 、 BoundedSemaphore 、 Condition 、 Event 、 Barrier 、 Queue 、 Value 和 Array 。
from multiprocessing import Process, Manager
def func(d, l):
d['name'] = 'yaowy'
d['age'] = 18
d['sex'] = 'M'
l.reverse()
if __name__ == '__main__':
with Manager() as manager:
d = manager.dict()
l = manager.list(range(10))
p = Process(target=func, args=(d, l))
p.start()
p.join()
print(d)
print(l)

使用服务进程的管理器比使用共享内存对象更灵活,因为它们可以支持任意对象类型。

浙公网安备 33010602011771号