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的Django框架中的Context使用
Jul 15 Python
Win10下Python环境搭建与配置教程
Nov 18 Python
Python多进程multiprocessing.Pool类详解
Apr 27 Python
python 实现在txt指定行追加文本的方法
Apr 29 Python
朴素贝叶斯分类算法原理与Python实现与使用方法案例
Jun 26 Python
Python 生成 -1~1 之间的随机数矩阵方法
Aug 04 Python
python 获取一个值在某个区间的指定倍数的值方法
Nov 12 Python
python3.6下Numpy库下载与安装图文教程
Apr 02 Python
python实现两个一维列表合并成一个二维列表
Dec 02 Python
TensorFlow命名空间和TensorBoard图节点实例
Jan 23 Python
Python环境搭建过程从安装到Hello World
Feb 05 Python
Python爬虫基础之初次使用scrapy爬虫实例
Jun 26 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
PDO防注入原理分析以及使用PDO的注意事项总结
2014/10/23 PHP
Zend Framework教程之路由功能Zend_Controller_Router详解
2016/03/07 PHP
详解PHP编码转换函数应用技巧
2016/10/22 PHP
用jQuery简化JavaScript开发分析
2009/02/19 Javascript
在一个浏览器里呈现所有浏览器测试结果的前端测试工具的思路
2010/03/02 Javascript
JavaScript代码复用模式实例分析
2012/12/02 Javascript
jquery 设置元素相对于另一个元素的top值(实例代码)
2013/11/06 Javascript
JavaScript获取Url里的参数
2014/12/18 Javascript
jQuery替换节点用法示例(使用replaceWith方法)
2016/09/08 Javascript
微信小程序教程之本地图片上传(leancloud)实例详解
2016/11/16 Javascript
Bootstrap基本插件学习笔记之标签切换(17)
2016/12/08 Javascript
jquery横向纵向鼠标滚轮全屏切换
2017/02/27 Javascript
VueJS如何引入css或者less文件的一些坑
2017/04/25 Javascript
详解VUE自定义组件中用.sync修饰符与v-model的区别
2018/06/26 Javascript
在vue项目中,将juery设置为全局变量的方法
2018/09/25 Javascript
jQuery事件多次绑定与解绑问题实例分析
2019/02/19 jQuery
微信小程序点击滚动到指定位置的实现
2020/05/22 Javascript
[46:27]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#2LGD VS MVP.Phx第一局
2016/03/02 DOTA
python重试装饰器示例
2014/02/11 Python
对变量赋值的理解--Pyton中让两个值互换的实现方法
2017/11/29 Python
python模块之paramiko实例代码
2018/01/31 Python
Python3.5基础之NumPy模块的使用图文与实例详解
2019/04/24 Python
python网络编程 使用UDP、TCP协议收发信息详解
2019/08/29 Python
完美解决pycharm 不显示代码提示问题
2020/06/02 Python
北美最大的零售退货翻新商:VIP Outlet
2019/11/21 全球购物
自我鉴定的范文
2013/10/03 职场文书
护士自我介绍信
2014/01/13 职场文书
岗位廉政承诺书
2014/03/27 职场文书
家庭教育的心得体会
2014/09/01 职场文书
校运动会广播稿(100篇)
2014/09/12 职场文书
2014年计划生育协会工作总结
2014/11/14 职场文书
银行客户经理岗位职责
2015/04/09 职场文书
集结号观后感
2015/06/08 职场文书
美容院管理规章制度
2015/08/05 职场文书
交通安全学习心得体会
2016/01/18 职场文书
python井字棋游戏实现人机对战
2022/04/28 Python