进程管道

本文探讨了进程管道及其与队列的关系。管道是队列的基础,但数据不安全,而队列通过加锁确保了数据安全。文中通过实例展示了如何使用管道进行进程间的通信,并解释了为何在使用管道时需要手动管理端口,以防进程阻塞。此外,还提到了管道在进程关闭后不会立即释放,需要通过EOFError来结束相关进程的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

管道:
基于socket 和pickle实现的
管道是队列的底层
数据不安全
源码对管道的解释:

The Pipe() function returns a pair of connection objects connected by a pipe which by default is duplex (two-way)
该函数返回一对连接用管道的默认两端的特征
 Each connection object has ***send()*** and ***recv()*** methods
 管道可以分为双工管道和单向管道。管道也是用队列的原理实现的。双工就是两边都可以存取信息。

管道也可以实现进程间的通信。但是进程间数据不安全。且存取数据复杂,
队列是基于管道实现的。管道是基于socket实现的。队列是管道的一种升级,基于管道中很多弊端形成了队列。
队列在进程中数据是安全的。因为两个队列不会同时取队列中的一个数据。也不会往同一个地方放数据。队列会严格的维持持续,不会有不安全的情况发送。
管道在进程之间数据不安全的。虽然管道也能实现IPC通信, 队列是管道加锁实现的,就是因为每次取数据和放数据时都添加了锁。所以永远不可能有两个进程同时修改一个队列了,

例1:
管道对象返回值

from multiprocessing import Pipe,Process
pipe = Pipe()
print(pipe)

运行结果

(<multiprocessing.connection.PipeConnection object at 0x0000019B2245A4E0>, <multiprocessing.connection.PipeConnection object at 0x0000019B2245A2E8>)    # 结果是管道的两端地址。可以元祖第一个收,第二个发

在一个进程中收发

from multiprocessing import Pipe
left, right = Pipe()  # 一个管道有两端
left.send(12345)  # 由于内部时基于socket和pickle实现的,所以不用传byte类型的,传任何数据类型都可以  # 左边传
print(right.recv())  # 右边收

运行结果

12345

例2:
用pipe写一个生产者消费者模型
pipe的端口管理不会随着某个进程的关闭就关闭,而是交给操作系统计数器做的。操作系统来管理进程对这些端口的使用。只有所有的进程都关闭了后才能感知到。如有两个进程,分别有两个端口,操作系统此时要管理4个端口。每关闭一个就-1,直到端口数目为剩1时。recv行为就报错。所有给我发信息的都关掉了,这时还recv就报错。所以必须手动把所有端口都关闭,归还操作系统资源。来触发EOFError,来结束某一个消费着的行为。否则即使所有代码都执行完,还是会在recv时阻塞。等着接收消息,因为不知道你还会不会给我发消息。

from multiprocessing import Pipe,Process
def consumer(left, right):
    left.close()
    while True:
        try:
            print(right.recv())
        except EOFError:
            break

if __name__ == '__main__':
    left, right = Pipe()
    Process(target=consumer, args=(left, right)).start()
    right.close()
    for i in range(10):
        left.send('%s' % i)
    left.close()

运行结果

0
1
2
3
4
5
6
7
8
9

例3:

from multiprocessing import Process, Pipe
def f(conn):
    conn.send([12, {'name': 'laura'}, 'hello'])
    response = conn.recv()
    print('response', response)  # response hello son!
    conn.close()
    print('q_ID2:', id(conn))  # q_ID2: 1576863392992

if __name__ == '__main__':
    parent_conn, child_conn = Pipe()
    print('q_ID1: ', id(child_conn))  # q_ID1:  1745512879552
    p = Process(target=f, args=(child_conn,))  
    p.start()
    print(parent_conn.recv())  # [12, {'name': 'laura'}, 'hello']
    parent_conn.send('hello son!')
    p.join()

运行结果

q_ID1:  1745512879552
[12, {'name': 'laura'}, 'hello']
response hello son!
q_ID2: 1576863392992

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值