Python Queue 入门

Queue 简介

Queue 叫队列,是数据结构中的一种,基本上所有成熟的编程语言都内置了对 Queue 的支持。

Python 中的 Queue 模块实现了多生产者和多消费者模型,当需要在多线程编程中非常实用。而且该模块中的 Queue 类实现了锁原语,不需要再考虑多线程安全问题。

该模块内置了三种类型的 Queue,分别是 class queue.Queue(maxsize=0),class queue.LifoQueue(maxsize=0) 和 class queue.PriorityQueue(maxsize=0)。它们三个的区别仅仅是取出时的顺序不一致而已。

Queue 是一个 FIFO 队列,任务按照添加的顺序被取出。

LifoQueue 是一个 LIFO 队列,类似堆栈,后添加的任务先被取出。

PriorityQueue 是一个优先级队列,队列里面的任务按照优先级排序,优先级高的先被取出。

Queue 常用操作

类和异常

class queue.Queue(maxsize=0)class queue.LifoQueue(maxsize=0)class queue.PriorityQueue(maxsize=0)

如你所见,就是上面所说的三种不同类型的内置队列,其中 maxsize 是个整数,用于设置可以放入队列中的任务数的上限。当达到这个大小的时候,插入操作将阻塞至队列中的任务被消费掉。如果 maxsize 小于等于零,则队列尺寸为无限大。

exception queue.Empty# 对空的 Queue 对象调用非阻塞的 get() (or get_nowait()) 时,会引发该异常。exception queue.Full# 对满的 Queue 对象调用非阻塞的 put() (or put_nowait()) 时,会引发该异常。

常用操作

1、添加任务

向队列中添加任务,直接调用 put() 函数即可

>>> import queue>>> q = queue.Queue(maxsize=1)>>> q.put(100)

put() 函数完整的函数签名如下 Queue.put(item, block=True, timeout=None),如你所见,该函数有两个可选参数。

默认情况下,在队列满时,该函数会一直阻塞,直到队列中有空余的位置可以添加任务为止。如果 timeout 是正数,则最多阻塞 timeout 秒,如果这段时间内还没有空余的位置出来,则会引发 Full 异常。

>>> import queue>>> q = queue.Queue(maxsize=1)>>> q.put(100)>>> q.put(100,True,2)Traceback (most recent call last): File “”, line 1, in File “E:Python37-32libqueue.py”, line 147, in put raise Fullqueue.Full # 创建一个容量为 1 的队列,2 秒内没有位置添加任务则引发 Full 异常>>> q.put(100) # 该方法会一直阻塞

当 block 为 false 时,timeout 参数将失效。同时如果队列中没有空余的位置可添加任务则会引发 Full 异常,否则会直接把任务放入队列并返回,不会阻塞。

>>> import queue>>> q = queue.Queue(maxsize=1)>>> q.put(100)>>> q.put(100,False,2)Traceback (most recent call last): File “”, line 1, in File “E:Python37-32libqueue.py”, line 136, in put raise Fullqueue.Full# 创建一个容量为 1 的队列,在第二次放入任务时指定为非阻塞模式,则会立刻引发 Full 异常

另外,还可以通过 Queue.put_nowait(item) 来添加任务,相当于 Queue.put(item, False),不再赘述。同样,在队列满时,该操作会引发 Full 异常。

2、获取任务

从队列中获取任务,直接调用 get() 函数即可。

>>> import queue>>> q = queue.Queue()>>> q.put(100)>>> q.get()100

与 put() 函数一样,get() 函数也有两个可选参数,完整签名如下 Queue.get(block=True, timeout=None)。

默认情况下,当队列空时调用该函数会一直阻塞,直到队列中有任务可获取为止。如果 timeout 是正数,则最多阻塞 timeout 秒,如果这段时间内还没有任务可获取,则会引发 Empty 异常。

>>> import queue>>> q = queue.Queue()>>> q.put(100)>>> q.get()100>>> q.get(True,2)Traceback (most recent call last): File “”, line 1, in File “E:Python37-32libqueue.py”, line 178, in get raise Empty_queue.Empty # 2 秒钟内没有任务可获取则引发 Empty 异常>>> q.get() # 该方法会一直阻塞

当 block 为 false 时,timeout 参数将失效。同时如果队列中没有任务可获取则会立刻引发 Empty 异常,否则会直接获取一个任务并返回,不会阻塞。

>>> import queue>>> q = queue.Queue()>>> q.put(100)>>> q.get()100>>> q.get(False,2)Traceback (most recent call last): File “”, line 1, in File “E:Python37-32libqueue.py”, line 167, in get raise Empty_queue.Empty # 指定为非阻塞模式,队列为空则立即引发 Empty 异常

另外,还可以通过 Queue.get_nowait() 来获取任务,相当于 Queue.get(False),不再赘述。同样,在队列为空时,该操作会引发 Empty 异常。

其他常用方法

1、获取队列大小

Queue.qsize() 函数返回队列的大小。注意这个大小不是精确的,qsize() > 0 不保证后续的 get() 不被阻塞,同样 qsize() < maxsize 也不保证 put() 不被阻塞。

>>> import queue>>> q = queue.Queue()>>> q.put(100)>>> q.put(200)>>> q.qsize()2

2、判断队列是否空

如果队列为空,返回 True ,否则返回 False 。如果 empty() 返回 True ,不保证后续调用的 put() 不被阻塞。类似的,如果 empty() 返回 False ,也不保证后续调用的 get() 不被阻塞。

3、判断队列是否满

如果队列是满的返回 True ,否则返回 False 。如果 full() 返回 True 不保证后续调用的 get() 不被阻塞。类似的,如果 full() 返回 False 也不保证后续调用的 put() 不被阻塞。

>>> import queue>>> q = queue.Queue(maxsize=1)>>> q.empty()True>>> q.full()False>>> q.put(100)>>> q.empty()False>>> q.full()True

队列对比

1、FIFO 队列

queue.Queue() 是 FIFO 队列,出队顺序跟入队顺序是一致的。

import queueq = queue.Queue()for index in range(10): q.put(index)while not q.empty(): print(q.get(), end=”, “)## 输出结果如下0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

2、LIFO 队列

queue.LifoQueue() 是 LIFO 队列,出队顺序跟入队顺序是完全相反的,类似于栈。

import queueq = queue.LifoQueue() # 创建一个 LIFO 队列for index in range(10): q.put(index)while not q.empty(): print(q.get(), end=”, “)## 输出结果如下9, 8, 7, 6, 5, 4, 3, 2, 1, 0,

3、优先级队列

优先级队列中的任务顺序跟放入时的顺序是无关的,而是按照任务的大小来排序,最小值先被取出。那任务比较大小的规则是怎么样的呢。

3.1 如果是内置类型,比如数值或者字符串,则按照自然顺序来比较排序。

import queueq = queue.PriorityQueue()for index in range(10,0,-1): q.put(index)while not q.empty(): print(q.get(), end=”, “)## 输出结果如下1, 2, 3, 4, 5, 6, 7, 8, 9, 10,

3.2 如果是列表或者元祖,则先比较第一个元素,然后比较第二个,以此类推,直到比较出结果

import queueq = queue.PriorityQueue()q.put([“d”,”b”])q.put([“c”,”b”])while not q.empty(): print(q.get(), end=”, “)## 输出结果如下[‘c’, ‘b’], [‘d’, ‘b’],

注意,因为列表的比较对规则是按照下标顺序来比较的,所以在没有比较出大小之前 ,队列中所有列表对应下标位置的元素类型要一致。

好比 [2,1] 和 [“1″,”b”] 因为第一个位置的元素类型不一样,所以是没有办法比较大小的,所以也就放入不了优先级队列。

然而对于 [2,1] 和 [1,”b”] 来说即使第二个元素的类型不一致也是可以放入优先级队列的,因为只需要比较第一个位置元素的大小就可以比较出结果了,就不需要比较第二个位置元素的大小了。

但是对于 [2,1] 和 1[2,”b”] 来说,则同样不可以放入优先级队列,因为需要比较第二个位置的元素才可以比较出结果,然而第二个位置的元素类型是不一致的,无法比较大小。

综上,也就是说,直到在比较出结果之前,对应下标位置的元素类型都是需要一致的。

3.3 如果是自定义类型,需要实现__lt__比较函数

下面我们自定义一个动物类型,希望按照年龄大小来做优先级排序。年龄越小优先级越高。

import queueq = queue.PriorityQueue()class Animal: def __init__(self, age, name): self.age = age self.name = name def __lt__(self, other): # 实现 < 操作 return self.age < other.age # 如果将 则相当于逆序q.put(Animal(3,"cat"))q.put(Animal(2,"dog"))while not q.empty(): animal = q.get() print(animal.name, animal.age, end=", ")## 输出结果如下dog 2, cat 3,

Queue 总结

本章节介绍了队列以及其常用操作。因为队列默认实现了锁原语,因此在多线程编程中就不需要再考虑多线程安全问题了,对于程序员来说相当友好了。

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年7月10日
下一篇 2022年7月10日

相关推荐

  • Chrome 105 发布啦

    Chrome 105 发布啦,这个版本带来了 25 个新特性,以及24个已知的安全修复程序,新特性如下: 脚本和样式表上的 “blocking=rendering” 属性 允许将 …

    2022年9月4日
  • SQL之SELECT语句-LIKE操作符

    LIKE操作符 通配符(wildcard)用来匹配值的一部分的特殊字符。 搜索模式(search pattern)由字面值、通配符或两者组合构成的搜索条件。 通配符本身实际是SQL…

    2022年6月19日
  • 两只靴子落地,该出手了

    郑重声明:本人内容仅为个人炒股笔记,不构成任何投资建议,据此操作,风险自担。我不会和任何粉丝有直接利益往来,冒充我身份和你合作,收费,荐股的全是骗子。

    2022年8月6日
  • 电脑文件怎么隐藏或显示文件后缀(扩展名)

    当想把文件扩展名隐藏或是显示的时候不知道该如何操作。今天就为大家介绍已知文件类型的扩展名如何设置显示与隐藏方法,来看看吧。 电脑文件怎么隐藏或显示文件后缀(扩展名) 1、点击打开“…

    2022年5月6日
  • 老人、孩子操作没难度,玥玛QL-B6可视猫眼智能锁到底有多香?

    锁之所以为锁,在于安全,在于防盗。 今日,注造锁十多年的老牌企业玥玛智能锁,推出了一款QL-B6可视猫眼智能锁,重磅防盗,双倍安全! 安全保护,一层又一层 独居女性,家中只有老人孩…

    2022年7月27日
  • 孔孝真这波操作属实赢“麻”了!私服穿搭慵懒随性,一点不显老

    对于“孔孝真”,我只能用四个字来形容,“天生丽质”虽然含义略显浮夸,但用在孔孝真身上一点也不过分。 今年42岁的孔孝真不但没有任何中年人的特征,反而越来越有韵味。因为孔孝真欧尼自身…

    2022年7月19日
  • AE中怎样输出图像序列

    Ae文件怎么导出png序列?ae中的文件想要导出序列,该怎么导出png序列呢? AE中怎样输出图像序列 1、打开Ae,新建项目,在项目面板中添加素材。 2、在菜单栏的“文件”中选择…

    2022年5月6日
  • cad撤销快捷键是什么(CAD撤销快捷键三种操作方法)

    CAD设计过程中,难免会出现各种CAD误操作的情况。那么,你知道CAD撤销命令快捷键是什么吗? CAD撤销命令快捷键: 1. U命令 其实U命令并不等于UNDO命令,执行两个命令的…

    2022年5月1日
  • 麻省理工开发出新型电池 成本只有同等大小锂离子电池的1/6

    麻省理工学院研究人员利用铝和硫作为电极材料,再加上熔盐电解质,开发出一种新型电池。这种铝-硫电池不仅成本低,而且安全,可用于家庭或中小企业供电以及电动汽车充电站。这项研究已于8月2…

    2022年8月29日
  • 一个神奇的函数:clip截断函数

    哈喽,大家中午好,今天给大家介绍一个神器的函数:clip截断函数。它之所以这么神奇,就在于它的雷厉风行,只能在它所设置的范围内,自由活动,一旦超出,就会被’和谐掉‘。下面具体介绍它…

    2022年6月20日

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息