Python进程间通信方式
作者:程序猿-张益达 发布时间:2021-12-03 03:08:39
一、通信方式
进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块主要通过队列方式
队列:队列类似于一条管道,元素先进先出
需要注意的一点是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态
二、Queue介绍
创建队列的类(底层就是以管道和锁定的方式实现):
Queue([maxsize]):创建共享的进程队列,Queue
是多进程安全的队列,
可以使用Queue实现多进程之间的数据传递。maxsize
是队列中允许最大项数,省略则无大小限制。
三、方法介绍
def put(self, obj, block=True, timeout=None):
插入数据到队列中,Block值默认为True,代表当队列已满时,会阻塞。如果block为False,则队列满会报异常Queue.Full,timeout表示会阻塞到指定时间,直到有剩余的空间供插入,如果时间超时,则报异常Queue.Fulldef get(self, block=True, timeout=None):从队列中取出数据,Block值默认为True,代表当队列为空时,会阻塞。如果block为False,则队列空会报异常Queue.Empty,timeout表示会等待到指定时间,直到取出数据,如果时间超时,则报异常Queue.Empty
def empty(self): 判断队列是否为空,如果空返回True
def full(self): 判断队列是否已满,如果满返回True
def qsize(self): 返回队列的大小
应用举例:
from multiprocessing import Process, Manager
q = Manager().Queue(2)
q.put(1)
q.put(2,block=False,timeout=2)
def func():
print(q.get())
p = Process(target=func)
print("size",q.qsize())
print("full",q.full())
p.start()
p.join()
print("empty",q.empty())
print("get", q.get())
print("get", q.get(block=False,timeout=2))
输出结果:
三、生产者和消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式?
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
四、什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯:
生产者,只需要往队列里面丢东西(生产者不需要关心消费者)
消费者,只需要从队列里面拿东西(消费者也不需要关心生产者)
阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
实现方式一:Queue
from multiprocessing import Process,Manager,active_children
import random
import queue
import time
class Producer(Process):
def __init__(self,queue):
super().__init__()
self.queue = queue
def run(self):
for i in range(6):
r = random.randint(0, 99)
time.sleep(1)
self.queue.put(r)
print("add data{}".format(r))
class Consumer(Process):
def __init__(self,queue):
super().__init__()
self.queue = queue
def run(self):
while True:
if not self.queue.empty():
data = self.queue.get()
print("minus data{}".format(data))
if __name__ == '__main__':
q = Manager().Queue() # 创建队列
p = Producer(q)
c = Consumer(q)
p.start()
c.start()
print(active_children()) # 查看现有的进程
p.join()
c.join()
print("结束")
>>>输出
[<ForkProcess(SyncManager-1, started)>, <Producer(Producer-2, started)>, <Consumer(Consumer-3, started)>]
add data83
minus data83
add data72
minus data72
add data8
minus data8
add data63
minus data63
add data75
minus data75
add data52
minus data52
实现方式二:利用JoinableQueue
JoinableQueue([maxsize]):一个Queue对象,但队列允许项目的使用者通知生成者项目已经被成功处理。通知进程是使用共享的信号和条件变量来实现的。JoinableQueue
的实例除了与Queue对象相同的方法之外还具有:
task_done():使用者使用此方法发出信号,表示get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,将引发ValueError异常
join():生产者调用此方法进行阻塞,直到队列中所有的项目均被处理。阻塞将持续到队列中的每个项目均调用task_done()方法为止
from multiprocessing import Process,JoinableQueue
import os
import time
import random
def print_log(msg, log_type="prod"):
if log_type == 'prod':
print("\033[32;1m%s\033[0m" %msg)
elif log_type == 'con':
print("\033[31;1m%s\033[0m" %msg)
def producer(q):
"""
生产者
:param q:
:return:
"""
for i in range(10):
data = random.randint(1,200)
time.sleep(2)
q.put(data) # 放入队列
msg = "add data {}".format(data)
print_log(msg)
q.join() # 生产者调用此方法进行阻塞,直到队列中所有的项目均被处理。
# 阻塞将持续到队列中的每个项目均调用q.task_done()方法为止
def consumer(q):
"""
消费者
:param q:
:return:
"""
while True:
if not q.empty():
time.sleep(5)
data = q.get()
msg = "minus data{}".format(data)
print_log(msg,"con")
q.task_done() # q.get()的返回项目已经被处理
if __name__ == '__main__':
q = JoinableQueue()
prod = Process(target=producer, args=(q,))
con = Process(target=consumer, args=(q,))
con.daemon = True # 设置为守护进程,但是不用担心,producer内调用q.join保证了consumer已经处理完队列中的所有元素
# 开启进程
prod.start()
con.start()
prod.join() # 等待生产和消费完成,主线程结束
print("结束")
输出结果:
来源:https://blog.csdn.net/weixin_41951954/article/details/123331551
猜你喜欢
- 01 实现我们几乎每个人都用过计算器,大家对于计算器应该都是比较熟悉的,计算器整体也是比较简单的,主要包括:显示器、键盘、运算的逻辑处理等,
- 本文为大家分享了机器学习10大经典算法,供大家参考,具体内容如下1、C4.5C4.5算法是机器学习算法中的一种分类决策树算法,其核心算法是I
- 本文实例为大家分享了python实现在线翻译的具体代码,供大家参考,具体内容如下具体效果请看图代码:import urllib.reques
- 最近跟着OpenCV2-Python-Tutorials在学习python_opencv中直方图的反向投影时,第一种方法是使用numpy实现
- 本文实例为大家分享了python自动发送邮件的具体代码,供大家参考,具体内容如下#coding=utf8 ''&
- 命令:Python manage.py runserver改为python manage.py runserver 0.0.0.0:80外网
- 防止一般的采集以及小偷读取,加在顶部。同理,可以改造成JS脚本。下面的方法是通过选择同一IP的访问频率来达到防止采集的目的,就是可能也把搜索
- 如下所示:加入代码:pd.set_option('display.width', 5000)补充知识:Python 实现不换
- 当我发现要写python的面向对象的时候,我是踌躇满面,坐立不安呀。我一直在想:这个坑应该怎么爬?因为python中关于面向对象的内容很多,
- 关于target="_blank"去留的问题在网上已经被反复争议很多次了。有的说要留,有的说要去掉。主张留的一方主要是考
- 本文实例为大家分享了python绘制汉诺塔的具体代码,供大家参考,具体内容如下源码:import turtleclass Stack: &n
- 1、终极方法:条件注释<!--[if lte IE 6]> 这段文字仅显示在 IE6及IE6以下版本。 <![endif]
- 为音视频自动生成字幕的 python 工具autosub 是一个能自动为音视频生成字幕的 python 包,以下为其简介和使用说明。auto
- 在 settings.py 中添加以下内容:LOGGING = { 'version': 1,
- N久没有开始写博客了,总觉得要随便记点东西,岁月蹉跎,曾经搞得一些东西、技术、工具,说丢也就丢了,点点滴滴还是要记录一下吧。。。在windo
- 用科讯CMS“分页显示(专题)文章列表标签”,可以在栏目文章列表下面产生一个页码行。从图可以看出,这段DIV,还需要CSS修饰,但是查看Ht
- 准备工作右击新建的项目,选择Python File,新建一个Python文件,然后在开头import cv2导入cv2库。转成灰度图像调用i
- 阅读上一篇教程:WEB2.0网页制作标准教程(7)CSS学习入门 CSS布局与传统表格(table)布局最大的区别在于:原来的定位都是采用表
- 1、实现效果2、实现步骤模块导入import os,sys,timefrom PyQt5 import QtCore,QtWidgets,Q
- 比如有两个模块,一个aa.py,一个bb.py 代码如下:aa.py:#encoding:utf-8import bba=1bb.py:#e