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读写excel的方法
Nov 18 Python
用Python将IP地址在整型和字符串之间轻松转换
Mar 22 Python
Python实现删除列表中满足一定条件的元素示例
Jun 12 Python
python Matplotlib画图之调整字体大小的示例
Nov 20 Python
python3 破解 geetest(极验)的滑块验证码功能
Feb 24 Python
python 中文件输入输出及os模块对文件系统的操作方法
Aug 27 Python
Python比较配置文件的方法实例详解
Jun 06 Python
Python 实现opencv所使用的图片格式与 base64 转换
Jan 09 Python
tensorflow 分类损失函数使用小记
Feb 18 Python
深入分析python 排序
Aug 24 Python
Django REST Framework 分页(Pagination)详解
Nov 30 Python
利用python实现汉诺塔游戏
Mar 01 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下目前为目最全的CURL中文说明
2010/08/01 PHP
PHP中break及continue两个流程控制指令区别分析
2011/04/18 PHP
php正则表达式使用的详细介绍
2013/04/27 PHP
PHP连接及操作PostgreSQL数据库的方法详解
2019/01/30 PHP
Mootools 1.2教程 设置和获取样式表属性
2009/09/15 Javascript
非常好用的JsonToString 方法 简单实例
2013/07/18 Javascript
在表单提交前进行验证的几种方式整理
2013/07/31 Javascript
2014最热门的JavaScript代码高亮插件推荐
2014/11/25 Javascript
JavaScript获取网页中第一个图片id的方法
2015/04/03 Javascript
整理AngularJS中的一些常用指令
2015/06/16 Javascript
Jquery基础之事件操作详解
2016/06/14 Javascript
详解vue-resource promise兼容性问题
2017/06/20 Javascript
解决VUEX刷新的时候出现数据消失
2017/07/03 Javascript
JS与jQuery判断文本框还剩多少字符可以输入的方法
2018/09/01 jQuery
js和jquery判断数据类型的4种方法总结
2020/08/28 jQuery
[56:46]Liquid vs IG 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
python采用getopt解析命令行输入参数实例
2014/09/30 Python
Python标准库之sqlite3使用实例
2014/11/25 Python
python pygame实现挡板弹球游戏
2019/11/25 Python
python求前n个阶乘的和实例
2020/04/02 Python
html5教你做炫酷的碎片式图片切换 (canvas)
2017/07/28 HTML / CSS
AmazeUI 导航条的实现示例
2020/08/14 HTML / CSS
台湾前三大B2C购物网站:MOMO购物网
2017/04/27 全球购物
意大利奢侈品牌在线精品店:Jole.it
2020/11/23 全球购物
JSP和EJB可以共享HttpSession么?EJB里面可以改变session里面的内容
2013/06/05 面试题
材料成型专业个人求职信范文
2013/09/25 职场文书
教师年终个人自我评价
2013/10/04 职场文书
企划专员岗位职责
2013/12/09 职场文书
商场中秋节广播稿
2014/01/17 职场文书
环保倡议书300字
2014/05/15 职场文书
低碳环保演讲稿
2014/08/28 职场文书
接待员岗位职责
2015/02/13 职场文书
出国留学自荐信模板
2015/03/06 职场文书
入党宣誓大会后的感想
2015/08/10 职场文书
SQL SERVER实现连接与合并查询
2022/02/24 SQL Server
Golang Elasticsearches 批量修改查询及发送MQ
2022/04/19 Golang