在不同的 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 对象。listQueue 被传递到了新进程,这个新进程有一个绑定函数 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 对象很容易被损坏。这就是为什么多进程编程时优先选择队列,因为队列提供了合适的进程间同步机制。

<完>

Python中,可以使用multiprocessing模块创建进程来并行处理任务,同时也可以使用该模块提供的Queue来实现多进程之间的数据共享和通信。下面是一个简单的例子,演示了如何在多个进程之间共享数据: ```python import multiprocessing def producer(queue): for i in range(10): queue.put(i) def consumer(queue): while True: item = queue.get() if item is None: break print(item) if __name__ == '__main__': queue = multiprocessing.Queue() p1 = multiprocessing.Process(target=producer, args=(queue,)) p2 = multiprocessing.Process(target=consumer, args=(queue,)) p1.start() p2.start() p1.join() queue.put(None) p2.join() ``` 在这个例子中,我们创建了一个Queue对象,并将其传递给两个进程。生产者进程通过put()方法将10个整数放入队列中,而消费者进程则不断地从队列中取出数据并打印。注意到我们在队列的末尾放了一个None对象,以此来告诉消费者进程已经没有数据可取了,可以结束了。 除了Queue之外,还可以使用multiprocessing模块提供的Pipe来实现进程间的通信。Pipe函数返回一对连接对象,分别代表管道的两端。我们可以通过这些连接对象向管道中发送和接收数据。下面是一个例子: ```python import multiprocessing def child(conn): conn.send([42, None, 'hello']) conn.close() if __name__ == '__main__': parent_conn, child_conn = multiprocessing.Pipe() p = multiprocessing.Process(target=child, args=(child_conn,)) p.start() print(parent_conn.recv()) # prints "[42, None, 'hello']" p.join() ``` 在这个例子中,我们创建了两个进程之间的管道,并将管道的一端传递给子进程。子进程通过send()方法向管道中发送一个列表,包含一个整数、一个None对象和一个字符串。父进程则通过recv()方法从管道中读取数据,打印出刚才子进程发送的列表。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dowhileprogramming

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值