Python学习笔记--并发编程之进程间通信(Pipe模块)

文章介绍了Python的multiprocessing库中Pipe和Queue模块在进程间通信中的作用,特别是管道如何通过消息传递实现单向或多向通信,以及如何通过Connection对象发送和接收数据。通过实例代码展示了如何创建并使用这两个机制进行子进程间的随机数交换。

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

mutliprocessing包提供了Pipe和Queue模块来实现进程间的通信,Pipe对应的是管道,Queue对应的是队列,这两种方式都是使用消息传递来进行通信。

小知识理解:

消息管理:计算机中的消息传递是一种通信的形式,例如在进程间的通信中,进程通过发送及接收消息的形式来实现同步。

管道:管道是计算机系统进行进程通信最原始的方式,管道又分为匿名管道和命名管道,匿名管道只能用于父子进程或者兄弟进程之间的通信,命名管道可以用于无亲情关系的进程。

队列:Python中的Queue是一种先进先出队列结构,在这种队列结构中,消息的生产者将消息存入队列中,消息的消费者从队列中取出消息。

Pipe模块是对进城管道通信机制的封装,在这种通信机制中,数据只能向一个方向流动。假设有A进程和B进程,进程A只能通过管道传输给进程B,或只能接收进程B发送过来的消息。进程间需要双方通信时,需要建立两个通道。

管道的实质是一个文件系统。数据只能向一个方向流动,意味着只能对管道进行读或写。使用管道来进行通信,可以理解为一个进程将数据写入管道,另一个进程从管道中读取数据,这样就实现了通信。

Pipe模块是multiprocessing包提供的一个方法,可以返回两个连接对象。语法为multiprocessing.Pipe([duplex]),返回值为元组类型,存储了两个Connection对象(conn1,conn2),分别表示管道的两端。

duplex的值默认为True,表示该管道是双向的,这里的双向是指返回的Connection对象既可以接收也可以发送消息。如果duplex被设置为False,那么该管道是单向的,即conn1只能用于接收消息,conn2只能用于发送消息。

Connection对象的操作方法如下:

(1)Connection.send(value)方法用来发送消息,value可以是任意数据类型。

(2)Connection.recv(value)方法用来从管道接收消息。

(3)Connection.close()方法关闭管道的读或写。

下面是一个使用管道进行进程通信的实例代码,使用Pipe让一个子进程从另一个子进程中收取随机数。

# 导入
from multiprocessing import Process,Pipe
import time
import random
import os

# 定义生产者函数,届时将生产者任务指派给子进程来进行处理
def producer(conn1):
    '''
    :param conn1 : Connection对象,执行send()方法给消费者进程
    :return :void ,无返回值
    '''

    # 执行os模块中的getid()方法来获取生产者进程的ID
    current_pid = os.getpid()
    print(f'生产者子进程的PID:{current_pid}')

    # 循环5次,发送5个随机数给到消费者进程
    for _ in range(5):
        conn1.send({"process_id":current_pid,"number":random.randint(0,1000)})
        time.sleep(0.5)

    # 发送一个None值给消费者进程,表示已停止发送
    conn1.send(None)

    # 在子进程中关闭Connection对象
    conn1.close()
 
# 定义消费者函数,届时将消费任务指派给子进程来进行处理
def consumer(conn2):
    '''
    :param conn2: Connection对象,执行recv()方法来接收从生产者进程发送的消息
    :return:void ,无返回值
    '''
    current_pid = os.getpid()
    print(f'消费者子进程的PID:{current_pid}')

    while True:
        # 执行recv()方法来接收从生产者进程发送的消息
        message = conn2.recv()
        time.sleep(0.5)
        if message:
            print('子进程{}收到了来自子进程{}的随机数:{}'.format(current_pid,message["process_id"],message["number"]))
        else:
            break    # 接收到了None消息,退出循环。
    
    # 在子进程中关闭Connection对象
    conn2.close()


if __name__ == '__main__':
    '''
    执行Pipe方法来返回一对Connection对象
    此时的Connection对象是在父进程中创建的
    Pipe模块的Pipe()方法返回一个元组,存储两个Connection对象,默认两个对象可以接收也可以发送消息
    '''
    # 元组的解包,分别赋给两个变量
    conn1,conn2 = Pipe()

    # 创建生产者子进程,同时将conn1对象传递给生产者子进程
    producer_process = Process(target=producer,args=(conn1,))

    # 创建消费者子进程,同时将conn2对象传递给消费者子进程
    consumer_process = Process(target=consumer,args=(conn2,))

    '''
    分别启动生产者和消费者子进程
    执行Process对象的start()方法后,Process对象会在内部执行run()方法
    在run()方法中会运行在target中指定的函数
    '''

    producer_process.start()
    consumer_process.start()

    '''
    在父进程中关闭这一对Connection对象
    管道的实质是文件,子进程引用了从父进程中传递的文件对象
    所以需要同时在父子进程之间进行关闭
    '''

    # 分别等待生产者进程和消费者进程结束
    producer_process.join()
    consumer_process.join()

    # 关闭Connection对象
    conn1.close()
    conn2.close()


运行如下图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值