一文看懂Python的多进程通信

1:Queue

queue用于不同进程间的通讯,但是一旦get出来,队列就会发生改变所以在get的时候应该判空

class Solution():
    def __init__(self):
        self.name = '乐乐熊'

def fun(q):
    time.sleep(2)
    q.put('JOKER')
    print('装填完毕')

def fnu(q):
    time.sleep(1)
    q.put([1,2,3,4,'ads'])
    print('装填完毕')


if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=fun,args=(q,))
    p2 = Process(target=fnu,args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print('P1,2进入阻塞')
    print(q.get())
    print(q.get())
    q.put(['asdasd'])
    print(q.get())
    print(q.qsize())

    # 加载c1,一个对象
    c1 = Solution()
    q.put(c1)
    print(type(q.get()))
    print(q.qsize())
    print('结束')

注,运行时如果在IDLE或者Spyder/Vscode等编辑器内运行,无法看到对应的进程显示信息,因此应该在cmd中运行Python ./xxx.py
在这里插入图片描述
可以看出Queue遵循着后入先出的规则,若有.get()前面一定会有.put()与之对应,在Queue中所有数据被get出来,其长度为0,此时若再次调用.get()方法,会报错,因此每次在调用get方法前一定要对当前的Queue大小进行判断,Queue不仅支持字符串、列表、数字的进程间传递,还支持对象的传递。

2:管道Pipe

Python中的管道支持双向传递和单向传递,其中单向传递结构如下所示:
在这里插入图片描述
通常主进程将信息发送到管道当中,子进程从管道中接收主进程发送的信息,一旦子进程接收到了该信息后,管道中的信息数减1,其他的子进程就无法获取该信息。而双向管道则是子进程也可以向主进程发送信息,主进程接收各个子进程发送的信息。下列代码向我们解释了双向管道的工作流程:

def func(conn):
    conn.send("message")

def fnuc(conn):
    conn.send('Newtest')

def jieshou(conn):
    print(conn.recv())

if __name__ == "__main__":
    (conn1,conn2) = Pipe()
    p1 = Process(target=func,args=(conn1,))
    p1.start()
    print(conn2.recv())
    p2 = Process(target=func,args=(conn2,))
    p2.start()
    print(conn1.recv())
    p3 = Process(target=fnuc,args=(conn2,))
    p3.start()
    print(conn1.recv())

    conn2.send('进程4测试')
    p4 = Process(target=jieshou,args=(conn1,))
    p4.start()
    p4.join()
    # 先进先出
    conn2.send('连续第1天')
    conn1.send('连续第2天')
    conn2.send('连续第3天')
    conn1.send('连续第4天')
    conn2.send('不连续了md')
    print(conn1.recv())
    print(conn1.recv())
    print(conn2.recv())
    print(conn2.recv())
    # print(conn1.recv())
    print('一切都结束了')

在这里插入图片描述
1:可以看出管道只能适用于两个进程一读一写的情况,管道只能一个端口发送一个端口接收,或者一个端口接收一个端口发送
2: 有多少个发送,就应当有多少个接收,可以连续用两个管道切换发送,接收的时候,左右两个管道切换接收即可
3:管道中的信息接收符合先入先出的规则
值得注意的是,管道没有东西的时候不能接收,会阻塞主进程

3:Manager

Manager可以建立一个全局共享变量,常用的共享变量有dict形式和list形式且共享变量支持上锁(Lock.acquire(),Lock.release()),下面针对dict形式进行详细说明

import time
from multiprocessing import Process,Queue,Pool,Manager,Pipe

class Solution():
    def __init__(self):
        self.name = '乐乐熊'
        self.age = 24

def add_data(p_dict,key,value):
    p_dict[key] = value

def show(p_dict):
    print(p_dict['3'].age)

def del_key(p_dict):
    p_dict["a"]=['zzh','zww','xzm','mym']


if __name__ == "__main__":
    progress = Manager().dict()
    c1 = Solution()
    progress['3']=c1
    p1 = Process(target=add_data,args=(progress,"a",1))
    p2 = Process(target=add_data,args=(progress,"b",2))
    p3 = Process(target=show,args=(progress,))
    p1.start()
    p2.start()
    p3.start()
    p1.join()
    p2.join()
    p3.join()
    print(progress['3'].name)
    print(progress)
    p4 = Process(target=del_key,args=(progress,))
    p4.start()
    p4.join()
    print(progress)

运行后结构显示如下:
在这里插入图片描述
分析结果,可以看出共享dict{}变化是实时的,子进程和主进程都可以对其进行修改。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值