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时间整形转标准格式的示例分享
Feb 14 Python
Python yield 使用浅析
May 28 Python
Python yield 使用方法浅析
May 20 Python
解决pycharm无法调用pip安装的包问题
May 18 Python
python实现linux下抓包并存库功能
Jul 18 Python
Python开发虚拟环境使用virtualenvwrapper的搭建步骤教程图解
Sep 19 Python
Flask实现跨域请求的处理方法
Sep 27 Python
django 自定义filter 判断if var in list的例子
Aug 20 Python
Django项目基础配置和基本使用过程解析
Nov 25 Python
python利用dlib获取人脸的68个landmark
Nov 27 Python
python模块内置属性概念及实例
Feb 18 Python
微信小程序调用python模型
Apr 21 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/02 无线电
在smarty中调用php内置函数的方法
2013/02/07 PHP
php面向对象与面向过程两种方法给图片添加文字水印
2015/08/26 PHP
PHP常用函数之格式化时间操作示例
2019/10/21 PHP
JQuery 常用操作代码
2010/03/14 Javascript
jquery trigger函数执行两次的解决方法
2016/02/29 Javascript
详解js树形控件—zTree使用总结
2016/12/28 Javascript
vue-dialog的弹出层组件
2020/05/25 Javascript
js常用的继承--组合式继承
2017/03/06 Javascript
jQuery实现的简单前端搜索功能示例
2017/10/28 jQuery
vue 项目常用加载器及配置详解
2018/01/22 Javascript
Angular6中使用Swiper的方法示例
2018/07/09 Javascript
nodejs更新package.json中的dependencies依赖到最新版本的方法
2018/10/10 NodeJs
大转盘抽奖小程序版 转盘抽奖网页版
2020/04/16 Javascript
微信内置开发 iOS修改键盘换行为搜索的解决方案
2019/11/06 Javascript
[01:49]一目了然!DOTA2DotA快捷操作对比第二弹
2014/05/16 DOTA
[33:17]OG vs VGJ.T 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
Python可跨平台实现获取按键的方法
2015/03/05 Python
Python使用random.shuffle()打乱列表顺序的方法
2018/11/08 Python
python实现对指定字符串补足固定长度倍数截断输出的方法
2018/11/15 Python
Flask框架模板继承实现方法分析
2019/07/31 Python
flask框架jinja2模板与模板继承实例分析
2019/08/01 Python
python自动化实现登录获取图片验证码功能
2019/11/20 Python
python 并发下载器实现方法示例
2019/11/22 Python
Python 格式化打印json数据方法(展开状态)
2020/02/27 Python
python实现飞船游戏的纵向移动
2020/04/24 Python
Python中实现输入一个整数的案例
2020/05/03 Python
学python需要去培训机构吗
2020/07/01 Python
python如何实现递归转非递归
2021/02/25 Python
英国假睫毛购买网站:FalseEyelashes.co.uk
2018/05/23 全球购物
普通党员四风问题对照检查材料
2014/09/27 职场文书
党委领导班子整改方案
2014/09/30 职场文书
群众路线教育实践活动学习心得体会
2014/10/30 职场文书
体育活动总结
2015/02/04 职场文书
校运会宣传稿大全
2015/07/23 职场文书
初中政治教学工作总结
2015/08/13 职场文书