脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|shell|

服务器之家 - 脚本之家 - Python - python多进程中的生产者和消费者模型详解

python多进程中的生产者和消费者模型详解

2023-03-27 12:09码上寒山石径斜 Python

这篇文章主要介绍了python多进程中的生产者和消费者模型,生产者是指生产数据的任务,消费者是指消费数据的任务。当生产者的生产能力远大于消费者的消费能力,生产者就需要等消费者消费完才能继续生产新的数据

Python生产者消费者模型

一、消费模式

生产者消费者模式 是Controlnet网络中特有的一种传输数据的模式。用于两个CPU之间传输数据,即使是不同类型同一厂家的CPU也可以通过设置来使用。

二、传输原理

  • 类似与点对点传送,又略有不同,一个生产者可以对应N个消费者,但是一个消费者只能对应一个生产者;
  • 每个生产者消费者对应一个地址,占一个网络节点,属于预定性数据,在网络中优先级最高;
  • 此模式如果在网络中设置过多会影响网络传输速度,一般用在传输比较重要的信息上,比如设备的启动、停止、故障、急停等等;
  • 在Controlnet网络中节点数是有限制的,最高节点数为99。
  • 如果两个控制器之前建立了多个生产者消费者的连接,只要一个失败,则所有的均失败,将数据整合到用户自定义结构或数组中 ,两个控制器中只保留一个连接。
  • 生产者消费者信息可以通过以太网和Controlnet传输,但是同时只能通过一种途径传输;
  • 建立标签时必须建立在全局变量里面,不能建立在局部变量里标签的大小不能超过500B;
  • 如果生产者几个数据传输到到同一个控制器的的几个消费者中,将几个数据合并在一个用户自定义标签中,可以减少连接数,但合并后的数据将会会用相同的RPI。
  • 生产者消费者标签只能用DINT和REAL,或它们的数组,或用户自定义结构数据,因为对外操作数据必须是32位的,如果有SINT和INT的数据要传输,必须将它们组合在用户自定义结构中传送,生产者和消费者的标签数据格式必须一致,才能确保数据的准确性,如果数据打包后超过了 32位,那么生产者和消费者双方必须使用一个复制缓冲指令,以获得数据的同步,例如Control Logix中的CPS指令。
  • 如果生产者要发送的32位数据,与非Control Logix的对方设备的数据结构不匹配,例如对方是16位的数据,为避免偏差,改为用户自定义结构。
  • 消费者的 RPI必须大于等于网络刷新时间NUT,如果几个消费者请求同一个生产者,则会以最小最快的RPI为准。

python多进程中的生产者和消费者模型详解

三、实现方式

方法一:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import threading,queue,time
# 创建一个队列,队列最大长度为2
q = queue.Queue(maxsize=2)
def product():
    while True:
        # 生产者往队列塞数据
        q.put('money')
        print('生产了money, 生产时间:', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
def consume():
    while True:
        time.sleep(0.5)
        # 消费者取出数据
        data = q.get()
        print('消费了%s, 消费时间%s' % (data, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
t = threading.Thread(target=product)
t1 = threading.Thread(target=consume)
t.start()
t1.start()

缺点:

    实现了多少个消费者consumer进程,就需要在最后往队列中添加多少个None标识,方便生产完毕结束消费者consumer进程。否则,p.get() 不到任务会阻塞子进程,因为while循环,直到队列q中有新的任务加进来,才会再次执行。而我们的生产者只能生产这么多东西,所以相当于程序卡死。

方法二:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from multiprocessing import JoinableQueue,Process
import time
def producer(q):
    for i in range(4):
        time.sleep(0.5)
        f = '生产者:已经生产'
        q.put(f)
        print(f)
    q.join()  # 一直阻塞,等待消耗完所有的数据后才释放
def consumer(name, q):
    while True:
        food = q.get()
        print('\033[消费者:消费了%s\033' % name)
        time.sleep(0.5)
        q.task_done()  # 每次消耗减1
if __name__ == '__main__':
    q = JoinableQueue()  # 创建队列
    # 模拟生产者队列
    p1 = Process(target=producer, args=(q, ))
    p1.start()
    # 模拟消费者队列
    c1 = Process(target=consumer, args=('money', q))
    c1.daemon = True  # 守护进程:主进程结束,子进程也会结束
    c1.start()
    p1.join()  # 阻塞主进程,等到p1子进程结束才往下执行

优点:参考地址

  • 使用JoinableQueue组件,是因为JoinableQueue中有两个方法:task_done()和join() 。首先说join()和Process中的join()的效果类似,都是阻塞当前进程,防止当前进程结束。但是JoinableQueue的join()是和task_down()配合使用的。
  • Process中的join()是等到子进程中的代码执行完毕,就会执行主进程join()下面的代码。而JoinableQueue中的join()是等到队列中的任务数量为0的时候才会执行q.join()下面的代码,否则会一直阻塞。
  • task_down()方法是每获取一次队列中的任务,就需要执行一次。直到队列中的任务数为0的时候,就会执行JoinableQueue的join()后面的方法了。所以生产者生产完所有的数据后,会一直阻塞着。不让p1和p2进程结束。等到消费者get()一次数据,就会执行一次task_down()方法,从而队列中的任务数量减1,当数量为0后,执行JoinableQueue的join()后面代码,从而p1和p2进程结束。
  • 因为p1和p2添加了join()方法,所以当子进程中的consumer方法执行完后,才会往下执行。从而主进程结束。因为这里把消费者进程c1和c2 设置成了守护进程,主进程结束的同时,c1和c2 进程也会随之结束,进程都结束了。所以消费者consumer方法也会结束。

到此这篇关于python多进程中的生产者和消费者模型详解的文章就介绍到这了,更多相关python生产者和消费者模型内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/wsq119/article/details/129756201

延伸 · 阅读

精彩推荐
  • Pythonselenium获取当前页面的url、源码、title的方法

    selenium获取当前页面的url、源码、title的方法

    这篇文章主要介绍了selenium获取当前页面的url、源码、title的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需...

    yonugleesin9462021-07-11
  • PythonPython中七种主要关键词提取算法的基准测试

    Python中七种主要关键词提取算法的基准测试

    我一直在寻找有效关键字提取任务算法。 目标是找到一种算法,能够以有效的方式提取关键字,并且能够平衡提取质量和执行时间,因为我的数据语料库迅...

    deephub10962021-11-26
  • Python使用IPython下的Net-SNMP来管理类UNIX系统的教程

    使用IPython下的Net-SNMP来管理类UNIX系统的教程

    这篇文章主要介绍了使用IPython下的Net-SNMP来管理类UNIX系统的教程,本文来自于IBM官方网站技术文档,需要的朋友可以参考下 ...

    脚本之家4892020-06-07
  • PythonPython通用验证码识别OCR库ddddocr的安装使用教程

    Python通用验证码识别OCR库ddddocr的安装使用教程

    dddd_ocr是一个用于识别验证码的开源库,又名带带弟弟ocr,下面这篇文章主要给大家介绍了关于Python通用验证码识别OCR库ddddocr的安装使用教程,文中通过示例代...

    PandaMan~9262022-07-07
  • Pythonpandas中df.rename()的具体使用

    pandas中df.rename()的具体使用

    本文主要介绍了pandas中df.rename()的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着...

    非昨3952022-08-15
  • Pythonpytorch 如何用cuda处理数据

    pytorch 如何用cuda处理数据

    考虑到各种运算只能在cpu或者gpu运算,不能混和运算,本文介绍常用的几种把数据挪到gpu或者直接在gpu创建数据再进行运算的方法...

    学渣渣渣渣渣11362021-11-19
  • PythonPython学习之面向对象编程详解

    Python学习之面向对象编程详解

    利用(面向)对象的(属性和方法)去进行编码的过程即面向对象编程。本文将通过示例详细为大家介绍一下Python中的面向对象编程,需要的可以参考一下...

    渴望力量的哈士奇7222022-10-28
  • PythonPython容错的前缀树实现中文纠错

    Python容错的前缀树实现中文纠错

    本文使用 Python 实现了前缀树,并且支持编辑距离容错的查询。文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    王大呀呀6122021-12-11