python-- 多进程队列 Queue、生成者和消费者

简介: python-- 多进程队列 Queue、生成者和消费者

多进程队列 Queue


# 栈:先进后出(First In Last Out       简称 FILO)
# 队列: 先进先出(First In First Out   简称 FIFO)
# 
# 
# import queue  不能进行多进程之间的数据传输
# from multiprocessing import Queue   借助Queue解决生产者消费者模型
# 队列是安全的。自带锁
from multiprocessing import Queue
q = Queue(num)  # num 队列的最大长度,为一个数字
q.get()  # 阻塞等待获取数据,如果有数据直接获取,如果没有数据,阻塞等待
q.put()  # 阻塞,如果可以直接往队列中放数据,就直接放,如果不能放,就阻塞等待
q.get_nowait()  # 不阻塞,如果有数据直接获取,没有数据就报错
q.put_nowait()  # 不阻塞,如果可以继续往队列中放数据,就直接放,不能放就报错

案例

from multiprocessing import Queue
q = Queue(3)  # 队列的最大长度
q.put(123)
q.put("abc")
q.put([4, 5, 6])
print(q.get())
print(q.get())
print(q.get())

结果:

123
abc
[4, 5, 6]

正常执行,队列的长度为3,添加了三个,获取了三个

from multiprocessing import Queue
q = Queue(3)  # 队列的最大长度
q.put(123)
q.put("abc")
q.put([4, 5, 6])
q.put(999)
print(q.get())
print(q.get())
print(q.get())

执行到q.put(999)阻塞,程序一直在等

from multiprocessing import Queue
q = Queue(3)  # 队列的最大长度
q.put(123)
q.put("abc")
q.put([4, 5, 6])
q.put_nowait(999)
print(q.get())
print(q.get())
print(q.get())

执行到q.put(999)报错

from multiprocessing import Queue
q = Queue(3)  # 队列的最大长度
q.put(123)
q.put("abc")
q.put([4, 5, 6])
print(q.get())
print(q.get())
print(q.get())
print(q.get_nowait())  # queue.Empty

执行到print(q.get_nowait())报错


生产者和消费者


生产者消费者模型主要是为解耦,借助队列来实现生产者消费者模型

from multiprocessing import Queue, Process
from time import sleep
def consumer(q, name):
    while 1:
        info = q.get()
        if info:
            print('%s 拿走了%s' % (name, info))
        else:  # 当消费者获得队列中数据时,如果获得的是None,就是获得到了生产者不再生产数据的标识
            break  # 此时消费者结束即可
def producer(q, product):
    for i in range(5):
        info = '生产了' + product + '版的娃娃%s号' % str(i)
        q.put(info)
        print(info)
    q.put(None)  # 让生产者生产完数据后,给消费者一个不再生产数据的标识
if __name__ == '__main__':
    q = Queue(5)
    pro = Process(target=producer, args=(q, '波多小姐'))
    con = Process(target=consumer, args=(q, '苍老师'))
    pro.start()
    con.start()

结果:

生产了波多小姐版的娃娃0号
生产了波多小姐版的娃娃1号
生产了波多小姐版的娃娃2号
生产了波多小姐版的娃娃3号
生产了波多小姐版的娃娃4号
苍老师 拿走了生产了波多小姐版的娃娃0号
苍老师 拿走了生产了波多小姐版的娃娃1号
苍老师 拿走了生产了波多小姐版的娃娃2号
苍老师 拿走了生产了波多小姐版的娃娃3号
苍老师 拿走了生产了波多小姐版的娃娃4号

改版上版的生产者和消费者

from multiprocessing import Queue, Process
import time
def consumer(q, name, color):
    while 1:
        info = q.get()
        if info:
            print('%s %s 拿走了%s \033[0m' % (color, name, info))
        else:  # 当消费者获得队列中数据时,如果获得的是None,就是获得到了生产者不再生产数据的标识
            break  # 此时消费者结束即可
def producer(q, product):
    for i in range(20):
        info = product + '的娃娃%s号' % str(i)
        q.put(info)
if __name__ == '__main__':
    q = Queue(10)
    p_pro1 = Process(target=producer, args=(q, '波多小姐'))
    p_pro2 = Process(target=producer, args=(q, '苍老师'))
    p_pro3 = Process(target=producer, args=(q, '小泽老师'))
    p_con1 = Process(target=consumer, args=(q, '麻老师', '\033[31m'))
    p_con2 = Process(target=consumer, args=(q, '王老师', '\033[32m'))
    p_l = [p_con1, p_con2, p_pro1, p_pro2, p_pro3]
    [i.start() for i in p_l]
    # 父进程如何感知到生产者子进程不再生产数据了?
    p_pro1.join()
    p_pro2.join()
    p_pro3.join()
    q.put(None)  # 几个消费者就要接受几个结束标识
    q.put(None)

结果

麻老师 拿走了波多小姐的娃娃0号 
 麻老师 拿走了波多小姐的娃娃2号 
 麻老师 拿走了波多小姐的娃娃3号 
 麻老师 拿走了波多小姐的娃娃4号 
 王老师 拿走了波多小姐的娃娃1号  麻老师 拿走了波多小姐的娃娃5号 
 麻老师 拿走了波多小姐的娃娃6号 
 王老师 拿走了波多小姐的娃娃7号 
 麻老师 拿走了波多小姐的娃娃8号 
 王老师 拿走了波多小姐的娃娃9号 
 麻老师 拿走了波多小姐的娃娃10号 
 王老师 拿走了波多小姐的娃娃11号 
 麻老师 拿走了波多小姐的娃娃12号 
 王老师 拿走了波多小姐的娃娃13号 
 麻老师 拿走了波多小姐的娃娃14号 
 王老师 拿走了波多小姐的娃娃15号 
 麻老师 拿走了波多小姐的娃娃16号 
 王老师 拿走了波多小姐的娃娃17号 
 麻老师 拿走了波多小姐的娃娃18号 
 王老师 拿走了波多小姐的娃娃19号 
 麻老师 拿走了苍老师的娃娃0号 
 王老师 拿走了苍老师的娃娃1号 
 麻老师 拿走了苍老师的娃娃2号 
 王老师 拿走了苍老师的娃娃3号 
 麻老师 拿走了苍老师的娃娃4号 
 王老师 拿走了苍老师的娃娃5号 
 麻老师 拿走了苍老师的娃娃6号 
 王老师 拿走了苍老师的娃娃7号 
 麻老师 拿走了苍老师的娃娃8号 
 王老师 拿走了苍老师的娃娃9号 
 麻老师 拿走了苍老师的娃娃10号 
 王老师 拿走了苍老师的娃娃11号 
 麻老师 拿走了苍老师的娃娃12号 
 王老师 拿走了苍老师的娃娃13号 
 麻老师 拿走了小泽老师的娃娃0号 
 王老师 拿走了苍老师的娃娃14号 
 麻老师 拿走了小泽老师的娃娃1号 
 王老师 拿走了苍老师的娃娃15号 
 麻老师 拿走了苍老师的娃娃16号 
 王老师 拿走了苍老师的娃娃17号 
 麻老师 拿走了苍老师的娃娃18号 
 王老师 拿走了小泽老师的娃娃2号 
 麻老师 拿走了苍老师的娃娃19号 
 王老师 拿走了小泽老师的娃娃3号 
 麻老师 拿走了小泽老师的娃娃4号 
 王老师 拿走了小泽老师的娃娃5号 
 麻老师 拿走了小泽老师的娃娃6号 
 王老师 拿走了小泽老师的娃娃7号 
 麻老师 拿走了小泽老师的娃娃8号 
 王老师 拿走了小泽老师的娃娃9号 
 麻老师 拿走了小泽老师的娃娃10号 
 王老师 拿走了小泽老师的娃娃11号 
 麻老师 拿走了小泽老师的娃娃12号 
 王老师 拿走了小泽老师的娃娃13号 
 麻老师 拿走了小泽老师的娃娃14号 
 王老师 拿走了小泽老师的娃娃15号 
 王老师 拿走了小泽老师的娃娃16号 
 麻老师 拿走了小泽老师的娃娃17号 
 王老师 拿走了小泽老师的娃娃18号 
 麻老师 拿走了小泽老师的娃娃19号


在改版

from multiprocessing import Process, JoinableQueue
q = JoinableQueue()
def consumer(q, name, color):
    while 1:
        info = q.get()
        print('%s %s 拿走了%s \033[0m' % (color, name, info))
        q.task_done()
def producer(q, product):
    for i in range(20):
        info = product + '的娃娃%s号' % str(i)
        q.put(info)
    q.join()  # 记录了生产了20个数据在队列中,此时会阻塞等待消费者消费完队列中所有数据
if __name__ == '__main__':
    q = JoinableQueue(10)
    p_pro1 = Process(target=producer, args=(q, '波多小姐'))
    p_con1 = Process(target=consumer, args=(q, '苍老师', '\033[31m'))
    p_con1.daemon = True  # 把消费者进程设为守护进程
    p_con1.start()
    p_pro1.start()
    p_pro1.join()  # 主进程等待生产者进程结束

结果:

苍老师 拿走了波多小姐的娃娃0号 
 苍老师 拿走了波多小姐的娃娃1号 
 苍老师 拿走了波多小姐的娃娃2号 
 苍老师 拿走了波多小姐的娃娃3号 
 苍老师 拿走了波多小姐的娃娃4号 
 苍老师 拿走了波多小姐的娃娃5号 
 苍老师 拿走了波多小姐的娃娃6号 
 苍老师 拿走了波多小姐的娃娃7号 
 苍老师 拿走了波多小姐的娃娃8号 
 苍老师 拿走了波多小姐的娃娃9号 
 苍老师 拿走了波多小姐的娃娃10号 
 苍老师 拿走了波多小姐的娃娃11号 
 苍老师 拿走了波多小姐的娃娃12号 
 苍老师 拿走了波多小姐的娃娃13号 
 苍老师 拿走了波多小姐的娃娃14号 
 苍老师 拿走了波多小姐的娃娃15号 
 苍老师 拿走了波多小姐的娃娃16号 
 苍老师 拿走了波多小姐的娃娃17号 
 苍老师 拿走了波多小姐的娃娃18号 
 苍老师 拿走了波多小姐的娃娃19号

程序有3个进程,主进程和生产者进程和消费者进程。当主进程执行到p_pro1.join()时,主进程会等待生产进程结束

而生产进程中(q.join())会等待消费者进程把所有数据消费完,生产者进程才结束。

现在的状态就是主进程等待生产者进程结束,生产者进程等待消费者消费完所有数据

所以,把消费者设置为守护进程,当主进程执行完,就代表生产进程已经结束,也就代表消费者进程已经把队列中数据消费完

此时,主进程一旦结束,守护进程也就是消费者进程也就跟着结束。整个程序也就能正常结束了。


相关文章
|
算法 调度 UED
深入理解操作系统:进程调度与优先级队列
【10月更文挑战第31天】在计算机科学的广阔天地中,操作系统扮演着枢纽的角色,它不仅管理着硬件资源,还为应用程序提供了运行的环境。本文将深入浅出地探讨操作系统的核心概念之一——进程调度,以及如何通过优先级队列来优化资源分配。我们将从基础理论出发,逐步过渡到实际应用,最终以代码示例巩固知识点,旨在为读者揭开操作系统高效管理的神秘面纱。
|
监控 编译器 Python
如何利用Python杀进程并保持驻留后台检测
本教程介绍如何使用Python编写进程监控与杀进程脚本,结合psutil库实现后台驻留、定时检测并强制终止指定进程。内容涵盖基础杀进程、多进程处理、自动退出机制、管理员权限启动及图形界面设计,并提供将脚本打包为exe的方法,适用于需持续清理顽固进程的场景。
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
442 0
|
数据采集 Java 数据处理
Python实用技巧:轻松驾驭多线程与多进程,加速任务执行
在Python编程中,多线程和多进程是提升程序效率的关键工具。多线程适用于I/O密集型任务,如文件读写、网络请求;多进程则适合CPU密集型任务,如科学计算、图像处理。本文详细介绍这两种并发编程方式的基本用法及应用场景,并通过实例代码展示如何使用threading、multiprocessing模块及线程池、进程池来优化程序性能。结合实际案例,帮助读者掌握并发编程技巧,提高程序执行速度和资源利用率。
901 0
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现智能食品消费者行为分析的深度学习模型
使用Python实现智能食品消费者行为分析的深度学习模型
455 4
|
并行计算 数据处理 调度
Python中的并发编程:探索多线程与多进程的奥秘####
本文深入探讨了Python中并发编程的两种主要方式——多线程与多进程,通过对比分析它们的工作原理、适用场景及性能差异,揭示了在不同应用需求下如何合理选择并发模型。文章首先简述了并发编程的基本概念,随后详细阐述了Python中多线程与多进程的实现机制,包括GIL(全局解释器锁)对多线程的影响以及多进程的独立内存空间特性。最后,通过实例演示了如何在Python项目中有效利用多线程和多进程提升程序性能。 ####
|
调度 iOS开发 MacOS
python多进程一文够了!!!
本文介绍了高效编程中的多任务原理及其在Python中的实现。主要内容包括多任务的概念、单核和多核CPU的多任务实现、并发与并行的区别、多任务的实现方式(多进程、多线程、协程等)。详细讲解了进程的概念、使用方法、全局变量在多个子进程中的共享问题、启动大量子进程的方法、进程间通信(队列、字典、列表共享)、生产者消费者模型的实现,以及一个实际案例——抓取斗图网站的图片。通过这些内容,读者可以深入理解多任务编程的原理和实践技巧。
1017 1
|
监控 JavaScript 前端开发
python中的线程和进程(一文带你了解)
欢迎来到瑞雨溪的博客,这里是一位热爱JavaScript和Vue的大一学生分享技术心得的地方。如果你从我的文章中有所收获,欢迎关注我,我将持续更新更多优质内容,你的支持是我前进的动力!🎉🎉🎉
338 0
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。
|
Linux Shell
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
1781 5

热门文章

最新文章

推荐镜像

更多