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的string模块中的Template类字符串模板用法
Jun 27 Python
Django 实现xadmin后台菜单改为中文
Nov 15 Python
python中利用matplotlib读取灰度图的例子
Dec 07 Python
Python hashlib加密模块常用方法解析
Dec 18 Python
python FTP批量下载/删除/上传实例
Dec 22 Python
python 操作mysql数据中fetchone()和fetchall()方式
May 15 Python
Python decimal模块使用方法详解
Jun 08 Python
利用python中的matplotlib打印混淆矩阵实例
Jun 16 Python
Python中正则表达式对单个字符,多个字符和匹配边界等使用
Jan 27 Python
Python的Tqdm模块实现进度条配置
Feb 24 Python
python常量折叠基础知识点讲解
Feb 28 Python
python-opencv 中值滤波{cv2.medianBlur(src, ksize)}的用法
Jun 05 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
是否存在第一台收音机的说法
2021/03/01 无线电
PHP APC配置文件2套和参数详解
2014/06/11 PHP
PHPstorm启用自动换行的方法详解(IDE)
2020/09/17 PHP
PHP之header函数详解
2021/03/02 PHP
用jquery实现等比例缩放图片效果插件
2010/07/24 Javascript
nodejs的require模块(文件模块/核心模块)及路径介绍
2013/01/14 NodeJs
js简单实现HTML标签Select联动带跳转
2013/10/23 Javascript
JavaScript 事件绑定及深入
2015/04/13 Javascript
Js实现无刷新删除内容
2015/04/29 Javascript
jQuery Mobile弹出窗、弹出层知识汇总
2016/01/05 Javascript
jQuery实现表格行和列的动态添加与删除方法【测试可用】
2016/08/01 Javascript
分享19个JavaScript 有用的简写写法
2017/07/07 Javascript
Vue 2.0在IE11中打开项目页面空白的问题解决
2017/07/16 Javascript
详解webpack-dev-server使用http-proxy解决跨域问题
2018/01/13 Javascript
Vue组件中的data必须是一个function的原因浅析
2018/09/03 Javascript
基于axios 解决跨域cookie丢失的问题
2018/09/26 Javascript
JavaScript实现左右滚动电影画布
2020/02/06 Javascript
Javascript幻灯片播放功能实现过程解析
2020/05/07 Javascript
Node 模块原理与用法详解
2020/05/13 Javascript
JS箭头函数和常规函数之间的区别实例分析【 5 个区别】
2020/05/27 Javascript
jQuery+css实现的点击图片放大缩小预览功能示例【图片预览 查看大图】
2020/05/29 jQuery
在Python中使用sort()方法进行排序的简单教程
2015/05/21 Python
Python pymongo模块用法示例
2018/03/31 Python
python 把列表转化为字符串的方法
2018/10/23 Python
python事件驱动event实现详解
2018/11/21 Python
使用PIL(Python-Imaging)反转图像的颜色方法
2019/01/24 Python
Python使用修饰器进行异常日志记录操作示例
2019/03/19 Python
Python解释器及PyCharm工具安装过程
2020/02/26 Python
keras之权重初始化方式
2020/05/21 Python
Python之Matplotlib文字与注释的使用方法
2020/06/18 Python
超市后勤自我鉴定
2014/01/17 职场文书
政治学求职信
2014/06/03 职场文书
2014年预备党员群众路线教育实践活动对照检查材料思想汇报
2014/10/02 职场文书
开学典礼观后感
2015/06/15 职场文书
JavaScript如何优化逻辑判断代码详解
2021/06/08 Javascript
python中pycryto实现数据加密
2022/04/29 Python