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实现挑选出来100以内的质数
Mar 24 Python
CentOS 7下Python 2.7升级至Python3.6.1的实战教程
Jul 06 Python
Python爬虫实例爬取网站搞笑段子
Nov 08 Python
TensorFlow利用saver保存和提取参数的实例
Jul 26 Python
python 实现分页显示从es中获取的数据方法
Dec 26 Python
Python实现FM算法解析
Jun 18 Python
Django Admin中增加导出CSV功能过程解析
Sep 04 Python
代码总结Python2 和 Python3 字符串的区别
Jan 28 Python
python中的 zip函数详解及用法举例
Feb 16 Python
tensorflow之tf.record实现存浮点数数组
Feb 17 Python
django ObjectDoesNotExist 和 DoesNotExist的用法
Jul 09 Python
python如何获得list或numpy数组中最大元素对应的索引
Nov 16 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
双料怀旧--SHARP GF515的维护、修理和简单调试
2021/03/02 无线电
PHP 和 MySQL 基础教程(三)
2006/10/09 PHP
PHP 远程关机实现代码
2009/11/10 PHP
PHP各种异常和错误的拦截方法及发生致命错误时进行报警
2016/01/19 PHP
yum命令安装php7和相关扩展
2016/07/04 PHP
JavaScript使用prototype定义对象类型(转)[
2006/12/22 Javascript
JQuery 自定义CircleAnimation,Animate方法学习笔记
2011/07/10 Javascript
js鼠标点击事件在各个浏览器中的写法及Event对象属性介绍
2013/01/24 Javascript
jquery ajax提交整个表单元素的快捷办法
2013/03/27 Javascript
JavaScript与Java正则表达式写法的区别介绍
2017/08/15 Javascript
35个最好用的Vue开源库(史上最全)
2019/01/03 Javascript
微信小程序地图(map)组件点击(tap)获取经纬度的方法
2019/01/10 Javascript
Layui数据表格跳转到指定页的实现方法
2019/09/05 Javascript
用Python编写一个简单的FUSE文件系统的教程
2015/04/02 Python
python使用pil生成图片验证码的方法
2015/05/08 Python
利用 Monkey 命令操作屏幕快速滑动
2016/12/07 Python
Sanic框架蓝图用法实例分析
2018/07/17 Python
Python操作qml对象过程详解
2019/09/26 Python
在pycharm中使用pipenv创建虚拟环境和安装django的详细教程
2020/11/30 Python
CSS3近阶段篇之酷炫的3D旋转透视
2016/04/28 HTML / CSS
韩国爱茉莉太平洋化妆品美国站:Amore Pacific US
2016/10/28 全球购物
美国著名的女性内衣零售商:Frederick’s of Hollywood
2018/02/24 全球购物
Room Mate Hotels美国:西班牙酒店品牌
2018/04/10 全球购物
印度化妆品购物网站:Nykaa
2018/07/22 全球购物
Rhone官方网站:男士运动服装、健身服装和高级运动服
2019/05/01 全球购物
Carrs Silver官网:英国著名的银器品牌
2020/08/29 全球购物
高二地理教学反思
2014/01/24 职场文书
《闻一多先生的说和做》教学反思
2014/04/28 职场文书
财务人员担保书
2014/05/13 职场文书
私营公司诉讼代理委托书范本
2014/09/13 职场文书
电工实训报告总结
2014/11/05 职场文书
新店开张宣传语
2015/07/13 职场文书
Java异常处理try catch的基本用法
2021/12/06 Java/Android
vue3引入highlight.js进行代码高亮的方法实例
2022/04/08 Vue.js
python实现手机推送 代码也就10行左右
2022/04/12 Python
openEuler 搭建java开发环境的详细过程
2022/06/10 Servers