Python中的多进程通信通常使用以下几种方法,选择通信方式取决于多进程间通信的需求和限制,可以根据不同的场景选择不同的通信机制:

Queue

Queue是Python标准库中提供的多进程通信机制,可以在多个进程之间传递数据。Queue是线程安全的,可以在多个进程之间安全地共享数据。

  • 创建一个例子程序
from multiprocessing import Process, Queue


def worker(queue):
    while True:
        item = queue.get()
        if item is None:
            break
        print("Worker received:", item)


def main():
    queue = Queue()
    processes = [Process(target=worker, args=(queue,)) for _ in range(2)]
    for p in processes:
        p.start()

    for i in range(10):
        queue.put(i)

    for p in processes:
        queue.put(None)

    for p in processes:
        p.join()


if __name__ == '__main__':
    main()

在这个例子中,我们创建了一个名为queue的队列,并在两个进程中分别运行了worker函数。在主进程中,我们循环10次并将数字放入队列中。在每个工作进程中,我们循环从队列中取出数字,直到队列为空为止。最后,我们等待所有进程完成后退出程序。

  • 运行结果
Worker received: 0
Worker received: 1
Worker received: 2
Worker received: 3
Worker received: 4
Worker received: 5
Worker received: 6
Worker received: 7
Worker received: 8
Worker received: 9

注意,每次运行结果可能不一样,因为多进程是并发执行的,所以每次的输出顺序可能不一样。

Pipes

Pipes是一种基于文件的通信机制,允许在多个进程之间传递数据。Pipes在较大的数据量和高带宽的需求中比Queue更有效。

  • 创建一个例子程序
import multiprocessing

def worker(conn):
    while True:
        msg = conn.recv()
        if msg == "exit":
            break
        print("Worker received:", msg)

if __name__ == "__main__":
    parent_conn, child_conn = multiprocessing.Pipe()
    process = multiprocessing.Process(target=worker, args=(child_conn,))
    process.start()
    for i in range(10):
        parent_conn.send(i)
    parent_conn.send("exit")
    process.join()

这段代码演示了如何使用Python中的multiprocessing模块的Pipe函数实现多进程通信。

代码中有两个进程:主进程和工作进程。

主进程负责创建工作进程,并与工作进程进行通信。主进程在启动工作进程后,通过parent_conn进行消息发送,把数字0到9发送到工作进程。最后,主进程发送“exit”消息以通知工作进程退出。

工作进程通过child_conn接收主进程发送的消息。当工作进程接收到“exit”消息时,它退出循环并终止。

运行上面的代码,会输出两个进程中间通信的消息,即从0到9的数字。

  • 运行结果
Worker received: 0
Worker received: 1
Worker received: 2
Worker received: 3
Worker received: 4
Worker received: 5
Worker received: 6
Worker received: 7
Worker received: 8
Worker received: 9

注意,每次运行结果可能不一样,因为多进程是并发执行的,所以每次的输出顺序可能不一样。

Manager

Manager是一种基于服务器的通信机制,可以在多个进程之间共享数据。Manager适用于多个进程需要同时访问数据的情况。

  • 创建一个例子程序
from multiprocessing import Process, Manager

def worker(d, l):
    d[1] = '1'
    d['2'] = 2
    d[0.25] = None
    l.reverse()

if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict()
        l = manager.list(range(10))

        print('Original data:')
        print(d)
        print(l)

        p = Process(target=worker, args=(d, l))
        p.start()
        p.join()

        print('Modified data:')
        print(d)
        print(l)

该代码示例创建了两个进程:主进程和工作进程。

主进程创建了一个字典对象d和一个列表对象l,使用Manager管理。

工作进程通过传递字典和列表作为参数,对字典和列表中的元素进行修改,把字典的值从1设置为字符串'1',把字典的键为'2'的值从2设置为整数2,把字典的键为0.25的值设置为空值,并把列表中的元素倒序排列。

最后,主进程等待工作进程完成,输出字典和列表的内容

  • 运行结果
Original data:
{}
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Modified data:
{0.25: None, 1: '1', '2': 2}
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Shared memory

Shared memory是一种内存共享技术,允许多个进程共享内存区域。Shared memory是最快的通信方式,但需要更加小心地处理,以避免冲突。

  • 给一个例子程序
import multiprocessing
import time

def worker(num, shm_obj):
    while True:
        print("Worker {} got value: {}".format(num, shm_obj.value))
        time.sleep(2)

def manager():
    shm = multiprocessing.Value('i', 0)
    p1 = multiprocessing.Process(target=worker, args=(1, shm,))
    p2 = multiprocessing.Process(target=worker, args=(2, shm,))

    p1.start()
    p2.start()

    for i in range(10):
        shm.value = i
        print("Manager set value to: {}".format(i))
        time.sleep(1)

    p1.join()
    p2.join()

if __name__ == '__main__':
    manager()

使用 multiprocessing.Value 创建一个共享内存对象。创建两个进程:p1 和 p2,分别作为两个工人。在管理进程中,使用 for 循环将 shm 的值更新为不同的整数。在两个工人进程中,使用 while 循环打印 shm.value

  • 运行结果
Manager set value to: 0
Worker 1 got value: 0
Worker 2 got value: 0
Manager set value to: 1
Worker 1 got value: 1
Worker 2 got value: 1
Manager set value to: 2
Worker 1 got value: 2
Worker 2 got value: 2
...

这是一个简单的多进程通信的示例,它说明了使用共享内存的多进程通信的方法。