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简单检测文本类型的2种方法【基于文件头及cchardet库】
Sep 18 Python
Python操作SQLite数据库的方法详解【导入,创建,游标,增删改查等】
Jul 11 Python
Python使用修饰器执行函数的参数检查功能示例
Sep 26 Python
python3模块smtplib实现发送邮件功能
May 22 Python
pyspark 读取csv文件创建DataFrame的两种方法
Jun 07 Python
pandas DataFrame实现几列数据合并成为新的一列方法
Jun 08 Python
python自定义函数实现一个数的三次方计算方法
Jan 20 Python
简单易懂Pytorch实战实例VGG深度网络
Aug 27 Python
Python通过正则库爬取淘宝商品信息代码实例
Mar 02 Python
python计算Content-MD5并获取文件的Content-MD5值方式
Apr 03 Python
聊聊Python pandas 中loc函数的使用,及跟iloc的区别说明
Mar 03 Python
python中sys模块的介绍与实例
Apr 17 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实现十进制、二进制、八进制和十六进制转换相关函数用法分析
2017/04/25 PHP
javascript中的location用法简单介绍
2007/03/07 Javascript
锋利的jQuery 要点归纳(一) jQuery选择器
2010/03/21 Javascript
Flash图片上传组件 swfupload使用指南
2015/03/14 Javascript
jQuery实现加入购物车飞入动画效果
2015/03/14 Javascript
jQuery超简单选项卡完整实例
2015/09/26 Javascript
jquery动态切换背景图片的简单实现方法
2016/05/14 Javascript
EasyUI加载完Html内容样式渲染完成后显示
2016/07/25 Javascript
DOM中事件处理概览与原理的全面解析
2016/08/16 Javascript
javascript用rem来做响应式开发
2018/01/13 Javascript
Vue的elementUI实现自定义主题方法
2018/02/23 Javascript
jquery的 filter()方法使用教程
2018/03/22 jQuery
elementUI 设置input的只读或禁用的方法
2018/10/30 Javascript
微信小程序自定义扫码功能界面的实现代码
2020/07/02 Javascript
three.js中多线程的使用及性能测试详解
2021/01/07 Javascript
[03:20]次级联赛厮杀超职业 现超级兵对拆世纪大战
2014/10/30 DOTA
python使用xlrd与xlwt对excel的读写和格式设定
2017/01/21 Python
Python实现可设置持续运行时间、线程数及时间间隔的多线程异步post请求功能
2018/01/11 Python
python中with语句结合上下文管理器操作详解
2019/12/19 Python
Python 调用 ES、Solr、Phoenix的示例代码
2020/11/23 Python
HTML5给汉字加拼音收起展开组件的实现代码
2020/04/08 HTML / CSS
京东全球售:直邮香港,澳门,台湾,美国,澳大利亚等地区
2017/09/24 全球购物
英国婴儿和儿童服装网站:Vertbaudet
2018/04/02 全球购物
越南母婴用品购物网站:Kids Plaza
2020/04/09 全球购物
环境科学专业个人求职信
2013/12/15 职场文书
公司年会演讲稿范文
2014/01/11 职场文书
2014年廉洁自律承诺书
2014/05/26 职场文书
超市促销活动总结
2014/07/01 职场文书
2014幼儿园教师师德师风演讲稿
2014/09/10 职场文书
领导干部作风建设自查报告
2014/10/23 职场文书
入党积极分子培养人意见
2015/06/02 职场文书
介绍信应该怎么开?
2019/04/03 职场文书
2019年恭贺升学祝福语集锦
2019/08/15 职场文书
浅谈Redis在直播场景的实践方案
2021/04/27 Redis
python如何利用cv2模块读取显示保存图片
2021/06/04 Python
python的netCDF4批量处理NC格式文件的操作方法
2022/03/21 Python