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 continue语句用法实例
Mar 11 Python
Python中使用PyQt把网页转换成PDF操作代码实例
Apr 23 Python
修改Python的pyxmpp2中的主循环使其提高性能
Apr 24 Python
Python django实现简单的邮件系统发送邮件功能
Jul 14 Python
python简单图片操作:打开\显示\保存图像方法介绍
Nov 23 Python
python实现NB-IoT模块远程控制
Jun 20 Python
selenium+python自动化测试环境搭建步骤
Jun 03 Python
使用Python自动生成HTML的方法示例
Aug 06 Python
使用Python将图片转正方形的两种方法实例代码详解
Apr 29 Python
如何把python项目部署到linux服务器
Aug 26 Python
pycharm安装深度学习pytorch的d2l包失败问题解决
Mar 25 Python
Python实现双向链表基本操作
May 25 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
PHP生成静态页面详解
2006/11/19 PHP
探讨:使用XMLSerialize 序列化与反序列化
2013/06/08 PHP
PHP和C#可共用的可逆加密算法详解
2015/10/26 PHP
XHProf报告字段含义的解析
2016/05/17 PHP
读jQuery之七 判断点击了鼠标哪个键的代码
2011/06/21 Javascript
初识SmartJS - AOP三剑客
2014/06/08 Javascript
JS+CSS实现Li列表隔行换色效果的方法
2015/02/16 Javascript
jquery.fastLiveFilter.js实现输入自动过滤的方法
2015/08/11 Javascript
js 定位到某个锚点的方法
2016/11/19 Javascript
JavaScript优化以及前段开发小技巧
2017/02/02 Javascript
Node.js开发第三方微信公众平台
2017/06/05 Javascript
Auto.js自动收取自己和好友蚂蚁森林能量脚本
2018/06/28 Javascript
TypeScript基础入门教程之三重斜线指令详解
2018/10/22 Javascript
JS实现长图上下滚动效果
2020/03/19 Javascript
Python中条件选择和循环语句使用方法介绍
2013/03/13 Python
python基础教程之类class定义使用方法
2014/02/20 Python
python+pyqt实现12306图片验证效果
2017/10/25 Python
Python数据结构与算法之常见的分配排序法示例【桶排序与基数排序】
2017/12/15 Python
PyQt5实现暗黑风格的计时器
2019/07/29 Python
Python学习笔记之Break和Continue用法分析
2019/08/14 Python
详解基于python的多张不同宽高图片拼接成大图
2019/09/26 Python
Python reduce函数作用及实例解析
2020/05/08 Python
python实现梯度下降算法的实例详解
2020/08/17 Python
利用纯css3实现的文字亮光特效的代码演示
2014/11/27 HTML / CSS
HTML5 Canvas+JS控制电脑或手机上的摄像头实例
2014/05/03 HTML / CSS
HTML5中在title标题标签里设置小图标的方法
2020/06/23 HTML / CSS
Mistine官方海外旗舰店:泰国国民彩妆品牌
2016/12/28 全球购物
英国厨房与餐具用品为主的设计品牌:Joseph Joseph
2018/04/26 全球购物
Oakley西班牙官方商店:太阳眼镜和男女运动服
2019/04/26 全球购物
测量实习生自我鉴定
2013/09/19 职场文书
售后服务承诺书模板
2014/05/21 职场文书
2015年保洁员工作总结
2015/05/04 职场文书
2016党员党章学习心得体会
2016/01/14 职场文书
2016学雷锋优秀志愿者事迹材料
2016/02/25 职场文书
ROS系统将python包编译为可执行文件的简单步骤
2021/07/25 Python
MySQL悲观锁与乐观锁的实现方案
2021/11/02 MySQL