Python 进程间的通信

这里先简述一下进程之间为什么要进行通信

我们要知道进程是资源分配的基本单位,不同进程之间的资源是独立的,没有关联,不能在一个进程中直接访问另一个进程资源

进程间通信的目的

  • 数据传输:一个进程需要将他的数据发送给另一个进程
  • 资源共享:多个进程之间共享同样的资源
  • 通知时间:一个进程需要向另一个进程发送消息,通知它们本进程发生了什么事情(如进程终止时要通知父进程)
  • 进程控制:有些进程希望完全控制另一个进程的执行(如 Debug 进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

Python中主要提供了两种进程间通信的方式

  1. multiprocessing模块下的Queue类提供了多个进程之间通信的方法
  2. pipe 管道,常用于实现2个进程间通信,这两个进程分别位于管道的两端

Queue实现进程间通信

Queue 实现进程间通信的方式,就是使用了操作系统给开辟的一个队列空间,各个进程可以把数据放到该队列中,当然也可以从队列中把自己需要的信息取走。

  • put( obj[ ,block=True [ ,timeout=None ] ] ) 将 obj 放入队列,其中当 block 参数设为 True 时,一旦队列被写满,则代码就会被阻塞,直到有进程取走数据并腾出空间供 obj 使用。timeout 参数用来设置阻塞的时间,即程序最多在阻塞 timeout 秒之后,如果还是没有空闲空间,则程序会抛出 queue.Full 异常。
  • empty() 判断当前队列空间是否为空,如果为空,则该方法返回 True;反之,返回 False。
  • get([block=True , [timeout=None] ]) 从队列中取数据并返回,当 block 为 True 且 timeout 为 None 时,该方法会阻塞当前进程,直到队列中有可用的数据。如果 block 设为 False,则进程会直接做取数据的操作,如果取数据失败,则抛出 queue.Empty 异常(这种情形下 timeout 参数将不起作用)。如果手动 timeout 秒数,则当前进程最多被阻塞 timeout 秒,如果到时依旧没有可用的数据取出,则会抛出 queue.Empty 异常。

示例
使用队列实现进程之间的信息通信

import os
import multiprocessing
def test(queue,name):
    #获取当前子进程编号
    print("子进程编号:", os.getpid())
    print(multiprocessing.current_process().pid,"往子进程中放数据:",name)
    #将 name 放入队列
    queue.put(name)
if __name__ == '__main__':
    # 创建进程通信的Queue
    queue = multiprocessing.Queue()
    # 获取当前进程的编号
    print("主进程编号:", os.getpid())
    # 创建子进程
    process = multiprocessing.Process(target=test, args=(queue,"jibu"))
    # 启动子进程
    process.start()
    #进程等待,该子进程必须先执行完毕
    process.join()
    print(multiprocessing.current_process().pid,"主进程从子进程中取数据:")
    print(queue.get())

结果
主进程编号: 15888
子进程编号: 18044
18044 往子进程中放数据: jibu
15888 主进程从子进程中取数据:
jibu

Pipe实现进程间通信

Pipe管道有 2 个口,而 Pipe 也常用来实现 2 个进程之间的通信,这 2 个进程分别位于管道的两端,一端用来发送数据,另一端用来接收数据。

使用 Pipe 实现进程通信,首先需要调用 multiprocessing.Pipe() 函数来创建一个管道。该函数的语法格式如下:

conn1, conn2 = multiprocessing.Pipe( [duplex=True] )

其中,conn1 和 conn2 分别用来接收 Pipe 函数返回的 2 个端口;duplex 参数默认为 True,表示该管道是双向的,即位于 2 个端口的进程既可以发送数据,也可以接受数据,而如果将 duplex 值设为 False,则表示管道是单向的,conn1 只能用来接收数据,而 conn2 只能用来发送数据。

Pipe可调用方法

  • send(obj) 发送一个 obj 给管道的另一端,另一端使用 recv() 方法接收。需要说明的是,该 obj 必须是可序列化的,如果该对象序列化之后超过 32MB,则很可能会引发 ValueError 异常。
  • recv() 接收另一端通过 send() 方法发送过来的数据。
  • close() 关闭连接。
  • poll([timeout]) 返回连接中是否还有数据可以读取。
import os
import multiprocessing
def test(conn,name):
    # 获取当前子进程编号
    print("子进程编号:", os.getpid())
    print(multiprocessing.current_process().pid,"子进程发送数据:",name)
    conn.send(name)
if __name__ == '__main__':
    # 获取当前进程的编号
    print("主进程编号:", os.getpid())
    #创建管道
    conn1,conn2 = multiprocessing.Pipe()
    # 创建子进程
    process = multiprocessing.Process(target=test, args=(conn1,"jibu"))
    # 启动子进程
    process.start()
    process.join()
    print(multiprocessing.current_process().pid,"主进程接收数据:")
    print(conn2.recv())

结果
主进程编号: 13848
子进程编号: 19208
19208 子进程发送数据: jibu
13848 主进程接收数据:
jibu
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

季布,

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值