您的位置:

Python 进程间通信

一、介绍

在一个复杂的应用程序中,通常会有多个进程同时运行,这些进程之间需要相互通信以实现各自的功能。进程间通信(IPC)是指在多进程之间传输数据或信号的方法。

二、IPC通信方式

Python 在进程间通信方面提供了多种通信方式,如下所示:

1. 管道(Pipe)

管道是一种全双工的通信方式,流向可以双向。在 Python 中,可以使用 os.pipe() 函数创建一个管道,该函数返回两个文件描述符,分别代表管道的读端和写端。管道适用于具有父子关系的进程之间的通信。下面是一个示例代码:

import os
r, w = os.pipe()
pid = os.fork()
if pid:
    os.close(w)
    r = os.fdopen(r)
    print("parent got '{0}'".format(r.read()))
else:
    os.close(r)
    w = os.fdopen(w, 'w')
    w.write('message from child')
    w.close()

2. 命名管道(FIFO)

命名管道也是一种全双工的通信方式,和管道类似,流向可以双向。不同的是,它可以跨越不同进程之间的通信。在 Python 中使用 os.mkfifo() 函数创建一个命名管道,该函数返回一个文件对象,可以像普通文件一样进行读写操作。下面是一个示例代码:

import os
fifo = '/tmp/myfifo'
if not os.path.exists(fifo):
    os.mkfifo(fifo)
pid = os.fork()
if pid:
    r = os.open(fifo, os.O_RDONLY)
    print("parent got '{0}'".format(os.read(r, 100)))
    os.close(r)
else:
    w = os.open(fifo, os.O_WRONLY)
    os.write(w, 'message from child')
    os.close(w)

3. 套接字(Socket)

套接字是一种更为通用的通信方式,它可以在不同的机器上的进程之间进行通信。在 Python 中,可以使用 socket.socket() 函数创建一个套接字对象,并使用 socket.bind() 函数将其绑定到一个特定的地址和端口上,然后使用 socket.listen() 函数监听连接请求,使用 socket.accept() 函数接受连接请求,并使用 socket.recv()socket.send() 函数进行读写操作。下面是一个示例代码:

import socket
host = ''
port = 5000
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(1)
conn, addr = sock.accept()
print('Connected by', addr)
data = conn.recv(1024)
conn.sendall(data)
conn.close()

4. 文件

文件是一种最简单的 IPC 通信方式,在不同进程之间传输文件可以使用共享内存(mmap)技术,这样多个进程可以共享同一个文件。在 Python 中,可以使用 os.open()os.close() 函数打开和关闭文件,使用 os.read()os.write() 函数进行读写操作。下面是一个示例代码:

import os
path = '/tmp/test.txt'
pid = os.fork()
if pid:
    with open(path) as f:
        print(f.read())
else:
    with open(path, 'w') as f:
        f.write('message from child')

三、进程池

Python 进程池为多进程提供了一种简单的方式,可以在多个进程间共享数据和资源。在 Python 中可以使用 concurrent.futures 库中的 ProcessPoolExecutor 类来创建进程池,使用 map() 函数来并行执行某个函数。下面是一个示例代码:

import concurrent.futures
def worker(data):
    return data * data
if __name__ == '__main__':
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = list(executor.map(worker, [1, 2, 3, 4, 5]))
    print(results)

四、消息队列

消息队列是一种异步通信方式,它将进程之间的通信变为一个事件驱动的过程。在 Python 中可以使用 queue 模块中的 Queue 类来创建消息队列,使用 put()get() 函数进行入队和出队。下面是一个示例代码:

import queue
q = queue.Queue()
q.put('message from parent')
pid = os.fork()
if pid:
    print(q.get())
else:
    print(q.get())
    q.put('message from child')

五、总结

Python 进程间通信提供了多种通信方式,选取合适的方式可以大大提高程序的性能和可读性。开发者在实际开发中应该结合具体情况进行选择。以上代码仅供参考,具体实现可以根据需求进行修改。