Python进程间通信Queue消息队列用法分析


Posted in Python onMay 22, 2019

本文实例讲述了Python进程间通信Queue消息队列用法。分享给大家供大家参考,具体如下:

进程间通信-Queue

Process之间有时需要通信,操作系统提供了很多机制来实现进程间的通信。

1. Queue的使用

可以使用multiprocessing模块的Queue实现多进程之间的数据传递,Queue本身是一个消息列队程序,首先用一个小实例来演示下Queue的工作原理:
代码如下:

#coding=utf-8
from multiprocessing import Queue
#初始化一个Queue对象,最多可接收三条put消息
q = Queue(3)
q.put('消息1')
q.put('消息2')
print(q.full())#False
q.put('消息3')
print(q.full())#True
#因为消息列队已满下面的try都会抛出异常,第一个try会等待2秒后再抛出异常,第二个Try会立刻抛出异常
try:
  q.put('消息4', True, 2)
except:
  print('消息队列已满,现有消息数量:%s'%q.qsize())
try:
  q.put_nowait('消息4')#等同于q.put('消息4', False)
except:
  print('消息队列已满,现有消息数量:%s'%q.qsize())
#推荐的方式,先判断消息列队是否已满,再写入
if not q.full():
  q.put_nowait('消息4')
#读取消息时,先判断消息列队是否为空,再读取
if not q.empty():
  for i in range(q.qsize()):
    print(q.get_nowait())

运行结果:

False
True
消息队列已满,现有消息数量:3
消息队列已满,现有消息数量:3
消息1
消息2
消息3

说明

初始化Queue()对象时(例如:q=Queue()),若括号中没有指定最大可接收的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限(直到内存的尽头);

Queue.qsize():返回当前队列包含的消息数量;
Queue.empty():如果队列为空,返回True,反之False ;
Queue.full():如果队列满了,返回True,反之False;
Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True;

1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果为空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为止,如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛出”Queue.Empty”异常;

2)如果block值为False,消息列队如果为空,则会立刻抛出”Queue.Empty”异常;
Queue.get_nowait():相当Queue.get(False);
Queue.put(item,[block[, timeout]]):将item消息写入队列,block默认值为True;

1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果已经没有空间可写入,此时程序将被阻塞(停在写⼊状态),直到从消息列队腾出空间为止。如果设置了timeout,则会等待timeout秒,若还没空间,则抛出”Queue.Full”异常;

2)如果block值为False,消息列队如果没有空间可写入则会立刻抛出”Queue.Full”异常;

Queue.put_nowait(item):相当Queue.put(item, False);

2. Queue实例

我们以Queue为例,在子进程中创建两个子进程,一个往Queue中写数据,一个从Queue中读数据:

#coding=utf-8
from multiprocessing import Queue, Process
import time, random, os
#写数据进程执行的代码
def write(q):
  l1 = ['A','B','C']
  for value in l1:
    print('put %s to queue...'%value)
    q.put(value)
    time.sleep(random.random())
#读数据执行的代码
def read(q):
  while True:
    if not q.empty():
      value = q.get(True)
      print('get %s from queue...' % value)
      time.sleep(random.random())
    else:
      break
if __name__ == "__main__":
  #父进程创建Queue,并传给各个子进程
  q = Queue()
  qw = Process(target=write, args=(q,))
  qr = Process(target=read, args=(q,))
  #启动子进程qw写入
  qw.start()
  qw.join()
  # 启动子进程qr写入
  qr.start()
  qr.join()
  # qr进程是死循环,无法等待其结束,只能强行终止:
  print('所有数据都已经写入并读取完毕')

运行结果:

put A to queue...
put B to queue...
put C to queue...
get A from queue...
get B from queue...
get C from queue...
所有数据都已经写入并读取完毕

3. 进程池中的Queue

如果要使用Pool创建进程,就需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue(),否则会得到一条如下的错误信息:

RuntimeError: Queue objects should only be shared between processes
through inheritance.

下面的实例演示了进程池中的进程如何通信:

代码如下:

#coding=utf-8
from multiprocessing import Manager, Pool
import time, random, os
def writer(q):
  print('writer启动%s,父进程为%s'%(os.getpid(),os.getppid()))
  l1 = ['a','b','c','d','e']
  for value in l1:
    q.put(value)
def reader(q):
  print('reader启动%s,父进程为%s'%(os.getpid(),os.getppid()))
  for i in range(q.qsize()):
    print('reader从Queue获取到消息:%s'%q.get(True))
if __name__ == "__main__":
  print('父进程%s启动...'%os.getpid())
  q = Manager().Queue() #使用Manager中的Queue来初始化
  po = Pool()
  # 使用阻塞模式创建进程,这样就不需要在reader中使用死循环了,可以让writer完全执行完成后,再用reader去读取
  po.apply(writer, (q,))
  po.apply(reader, (q,))
  po.close()
  po.join()
  print('%s结束'%os.getpid())

运行结果:

父进程7415启动...
writer启动7421,父进程为7415
reader启动7422, 父进程为7415
reader从Queue获取到消息:a
reader从Queue获取到消息:b
reader从Queue获取到消息:c
reader从Queue获取到消息:d
reader从Queue获取到消息:e
7415结束

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
python的三目运算符和not in运算符使用示例
Mar 03 Python
PHP网页抓取之抓取百度贴吧邮箱数据代码分享
Apr 13 Python
Python下载网络文本数据到本地内存的四种实现方法示例
Feb 05 Python
python openvc 裁剪、剪切图片 提取图片的行和列
Sep 19 Python
Python 音频生成器的实现示例
Dec 24 Python
深入浅析Python 命令行模块 Click
Mar 11 Python
Python+OpenCV图像处理——实现轮廓发现
Oct 23 Python
Python爬虫+tkinter界面实现历史天气查询的思路详解
Feb 22 Python
python实现计算图形面积
Feb 22 Python
Python绘制词云图之可视化神器pyecharts的方法
Feb 23 Python
 分享一个Python 遇到数据库超好用的模块
Apr 06 Python
Python+pyaudio实现音频控制示例详解
Jul 23 Python
将python文件打包成EXE应用程序的方法
May 22 #Python
Python多线程threading模块用法实例分析
May 22 #Python
Python3之手动创建迭代器的实例代码
May 22 #Python
PyTorch搭建一维线性回归模型(二)
May 22 #Python
PyTorch基本数据类型(一)
May 22 #Python
PyTorch搭建多项式回归模型(三)
May 22 #Python
pytorch使用Variable实现线性回归
May 21 #Python
You might like
火车头采集器3.0采集图文教程
2007/03/17 PHP
PHP简单获取及判断提交来源的方法
2016/04/22 PHP
PHP中localeconv()函数的用法
2019/03/26 PHP
js中判断文本框是否为空的两种方法
2011/07/31 Javascript
浅谈jquery设置和获得checkbox选中的问题
2016/08/19 Javascript
利用JavaScript判断浏览器类型及版本
2016/08/23 Javascript
JS树形菜单组件Bootstrap TreeView使用方法详解
2016/12/21 Javascript
nodejs中Express与Koa2对比分析
2018/02/06 NodeJs
详解使用jQuery.i18n.properties实现js国际化
2018/05/04 jQuery
Node.js系列之连接DB的方法(3)
2019/08/30 Javascript
JS代码触发事件代码实例
2020/01/02 Javascript
ES6 Object.assign()的用法及其使用
2020/01/18 Javascript
WEB前端性能优化的7大手段详解
2020/02/04 Javascript
微信小程序实现上传照片代码实例解析
2020/08/04 Javascript
vue 里面的 $forceUpdate() 强制实例重新渲染操作
2020/09/21 Javascript
在Python中使用HTMLParser解析HTML的教程
2015/04/29 Python
Python yield 使用浅析
2015/05/28 Python
浅谈python为什么不需要三目运算符和switch
2016/06/17 Python
在CMD命令行中运行python脚本的方法
2018/05/12 Python
对python中的six.moves模块的下载函数urlretrieve详解
2018/12/19 Python
python交互模式下输入换行/输入多行命令的方法
2019/07/02 Python
Python如何使用Gitlab API实现批量的合并分支
2019/11/27 Python
Pycharm最新激活码2019(推荐)
2019/12/31 Python
Python for循环通过序列索引迭代过程解析
2020/02/07 Python
Django静态文件加载失败解决方案
2020/08/26 Python
CSS3线性渐变简单实现以及该属性在浏览器中的不同
2012/12/12 HTML / CSS
应届毕业生自我鉴定范文
2013/12/27 职场文书
采购主管岗位职责
2014/02/01 职场文书
《第一朵杏花》教学反思
2014/04/16 职场文书
物理系毕业生自荐书
2014/06/13 职场文书
保卫工作个人总结
2015/03/03 职场文书
单位介绍信格式范文
2015/05/04 职场文书
2015年助理政工师工作总结
2015/05/26 职场文书
少先队中队工作总结2015
2015/07/23 职场文书
2016教师党员学习心得体会
2016/01/21 职场文书
Java基础——Map集合
2022/04/01 Java/Android