pin_drop当前位置:知识文库 ❯ 图文
进程间通信Pipe详解 - Python双向管道send/recv
概述
multiprocessing.Pipe 是Python多进程模块提供的双向管道通信机制。与Queue不同,Pipe创建的是两个连接端点,通常用于两个进程之间的高效数据交换。
Pipe的底层基于操作系统管道实现,数据以字节流的形式在管道中传输。它比Queue更轻量、更快,但不支持多对多通信场景。当需要在两个进程间进行双向对话时,Pipe是理想选择。
语法
代码示例
from multiprocessing import Process, Pipe
# 创建管道
parent_conn, child_conn = Pipe(duplex=True)
# 参数说明:
# duplex: True为双向管道(默认),False为单向管道
# - duplex=True: 两个端点都可以send和recv
# - duplex=False: 第一个端点只能recv,第二个端点只能send
# 连接端点的常用方法:
# conn.send(obj) — 发送对象(自动pickle序列化)
# conn.recv() — 接收对象(阻塞等待)
# conn.poll(timeout) — 检查是否有数据可读
# conn.close() — 关闭连接基本用法
双向通信
代码示例
from multiprocessing import Process, Pipe
def child_process(conn):
"""子进程:接收父进程消息并回复"""
msg = conn.recv()
print(f"子进程收到: {msg}")
conn.send("你好,父进程!")
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=child_process, args=(child_conn,))
p.start()
parent_conn.send("你好,子进程!")
reply = parent_conn.recv()
print(f"父进程收到: {reply}")
p.join()单向管道
代码示例
from multiprocessing import Process, Pipe
def sender(conn):
"""发送端"""
for i in range(5):
conn.send(f"消息{i}")
conn.close()
def receiver(conn):
"""接收端"""
while conn.poll():
msg = conn.recv()
print(f"收到: {msg}")
conn.close()
if __name__ == '__main__':
# duplex=False: recv_conn只能接收, send_conn只能发送
recv_conn, send_conn = Pipe(duplex=False)
p1 = Process(target=sender, args=(send_conn,))
p2 = Process(target=receiver, args=(recv_conn,))
p1.start()
p2.start()
p1.join()
p2.join()代码示例
示例:请求-响应模式
代码示例
from multiprocessing import Process, Pipe
import time
def server(conn):
"""服务端:接收请求,返回响应"""
while True:
request = conn.recv()
if request == "QUIT":
break
print(f"服务端收到请求: {request}")
time.sleep(0.5) # 模拟处理时间
response = f"已处理: {request}"
conn.send(response)
conn.close()
print("服务端关闭")
def client(conn):
"""客户端:发送请求,等待响应"""
requests = ["查询用户", "更新数据", "删除记录"]
for req in requests:
conn.send(req)
response = conn.recv()
print(f"客户端收到响应: {response}")
conn.send("QUIT")
conn.close()
print("客户端关闭")
if __name__ == '__main__':
conn1, conn2 = Pipe()
s = Process(target=server, args=(conn1,))
c = Process(target=client, args=(conn2,))
s.start()
c.start()
s.join()
c.join()注意事项
注意1:多个进程同时写入同一个Pipe端点可能导致数据损坏。如果需要多进程写入,应使用Queue或自行加锁。
注意2:使用完毕后应调用
conn.close()关闭连接端点,避免资源泄漏。
注意3:使用
poll(timeout)可以在接收前检查是否有数据可读,避免recv()无限阻塞。
小结
-
Pipe:创建双向管道,返回两个连接端点,适合两进程间通信
-
send/recv:send发送对象,recv接收对象,均自动pickle序列化
-
性能优势:比Queue更轻量快速,适合一对一通信场景
-
限制:不支持多对多通信,多进程写入需额外同步
练习题
练习1
编写程序,使用Pipe实现父子进程间的双向通信:父进程发送一组数字给子进程,子进程计算它们的平方后返回给父进程。
练习2
编写一个函数,使用Pipe实现一个简单的"ping-pong"游戏:两个进程交替发送和接收消息,模拟乒乓球来回,直到达到指定次数后结束。
常见问题
Pipe和Queue应该如何选择?
如果是严格的一对一双向通信且追求性能,选择Pipe。如果需要多生产者多消费者的任务分发场景,选择Queue。Queue更安全方便,Pipe更快但使用限制更多。
Pipe传递的数据有大小限制吗?
操作系统管道有缓冲区大小限制(通常64KB左右)。如果发送的数据超过缓冲区大小,send()会阻塞直到接收端取走数据。对于大数据量传输,建议分块发送或使用共享内存。
如何检测Pipe中是否有数据可读?
使用conn.poll(timeout)方法。不传参数时立即返回True/False表示是否有数据;传入timeout参数(秒)则会等待指定时间。这可以避免recv()无限阻塞。
本文涉及AI创作
内容由AI创作,请仔细甄别