在不同的 Python 进程中交换 Python 对象
在不同的 Python 进程中交换 Python 对象
在前面的节中,我们讲解了怎么在进程中共享数据,这是通过使用一个新的进程(服务进程)或外部内存(共享内存)实现的。在这一节中,我们讲解在进程中文换 Python 对象。multiprocessing 模块提供了两个选项用来实现这个功能,分别是使用 Queue 对象和 Pipe 对象。
使用 Queue 对象
在 multiprocessing 包中可见的 Queue 对象,它几乎和我们在多线程编程中用到的同步队列对象(queue.Queue)是相同的。Queue 是进程安全的,不需要任何附加的保护。下面的代码演示了用多进程 Queue 对象交换数据:
import multiprocessing
from multiprocessing import Process, Queue
def copy_data(list, myqueue):
for num in list:
myqueue.put(num)
def output(myqueue):
while not myqueue.empty():
print(myqueue.get())
def main():
mylist = [2, 5, 7]
myqueue = Queue()
p1 = Process(target=copy_data, args=(mylist, myqueue))
p2 = Process(target=output, args=(myqueue,))
p1.start()
p1.join()
p2.start()
p2.join()
print("队列是否为空:", myqueue.empty())
print("主进程退出。")
if __name__ == '__main__':
main()
上面代码的输出结果是:
2
5
7
队列是否为空: True
主进程退出。
在上面的示例中,我们创建了一个标准的 list 对象和一个多进程 Queue 对象。list 和 Queue 被传递到了新进程,这个新进程有一个绑定函数 copy_data。这个函数会把数据从 list 对象复制到 Queue 对象中。另一个新进程被创建用来输出 Queue 对象的内容。注意,Queue 中的数据由前一个进程设置,并且对后面的新进程可见。这是一种方便的交换数据的方式,它没有共享内存和服务进程的复杂性。
使用 Pipe 对象
Pipe 对像两个进程之前的管道一样,可以用来交换数据。当需要双向通信时,这一种方法非常有用。当我们创建一个 Pipe 对象时,它提供两个连接对象,代表了 Pipe 对象的两端。每一个连接对象都提供了发送数据的 send 和 接收数据的 recv 方法。
为了解释清楚 Pipe 对象,我们创建了两个函数,附加到两个独立的进程上:
- 第一个函数用来通过
Pipe对象的连接发送数据。我们会发送一些数据消息,并且以BYE消息结束通信; - 第二个函数使用
Pipe对象的连接接收消息。这个函数会运行一个无限循环,直到收到一个BYE消息。
我们给这两个函数(或进程)提供了一个管道的一个连接。下面是完整的代码:
from multiprocessing import Process, Pipe
def mysender(s_conn):
s_conn.send({1, "数学"})
s_conn.send({2, "语文"})
s_conn.send({3, "英语"})
s_conn.send('BYE')
def myreceiver(r_conn):
while True:
msg = r_conn.recv()
print("接收到的消息是:", msg)
if msg == 'BYE':
break
def main():
sender_conn, receiver_conn = Pipe()
p1 = Process(target=mysender, args=(sender_conn,))
p2 = Process(target=myreceiver, args=(receiver_conn,))
p1.start()
p2.start()
p1.join()
p2.join()
print("退出主进程。")
if __name__ == '__main__':
main()
上面代码的输出结果是:
接收到的消息是: {1, '数学'}
接收到的消息是: {2, '语文'}
接收到的消息是: {3, '英语'}
接收到的消息是: BYE
退出主进程。
有一点需要注意, 当两个进程尝试在同一时间读或写同一个连接对象时,Pipe 对象很容易被损坏。这就是为什么多进程编程时优先选择队列,因为队列提供了合适的进程间同步机制。
<完>
769

被折叠的 条评论
为什么被折叠?



