Python队列Queue详解,超详细

简介: Python队列Queue详解,超详细

queue模块简介


queue模块是Python内置的标准模块,模块实现了三种类型的队列,它们的区别仅仅是条目取回的顺序,分别由3个类进行表示,Queue,LifoQueue,PriorityQueue


queue.Queue(maxsize=0)


先进先出队列

maxsize 是个整数,用于设置可以放入队列中的项目数的上限。当达到这个大小的时候,插入操作将阻塞至队列中的项目被消费掉。如果 maxsize 小于等于零,队列尺寸为无限大。


from queue import Queue
# FIFO
queue_obj = Queue()  # 创建一个队列对象
for i in range(4):
    queue_obj.put(i)
while not queue_obj.empty():
    print(queue_obj.get())
# 输出顺序
0
1
2
3


queue.LifoQueue(maxsize=0)


后进先出,maxsize和Queue一样

from queue import Queue,LifoQueue
# LIFO
queue_obj = LifoQueue()  # 创建一个队列对象
for i in range(4):
    queue_obj.put(i)
while not queue_obj.empty():
    print(queue_obj.get())
# 输出顺序
3
2
1
0


queue.PriorityQueue(maxsize=0)


优先级队列构造器,按照级别顺序取出元素,级别最低的最先取出

队列中的元素一般采取元组的形式进行存储(priority_number, data)

  • 优先级不同数据部分可以比较大小
PriorityQueue_obj = PriorityQueue()
PriorityQueue_obj.put((5,45))
PriorityQueue_obj.put((1,42))
PriorityQueue_obj.put((2,47))
while not PriorityQueue_obj.empty():
    print(PriorityQueue_obj.get())
# 输出顺序
(1, 42)
(2, 47)
(5, 45)
  • 优先级一样,数据部分可以比较大小
priorityQueue_obj = PriorityQueue()
priorityQueue_obj.put((1,45))
priorityQueue_obj.put((1,42))
priorityQueue_obj.put((1,47))
while not PriorityQueue_obj.empty():
    print(PriorityQueue_obj.get())
(1, 42)
(1, 45)
(1, 47)
priorityQueue_obj = PriorityQueue()
priorityQueue_obj.put((1,[1,4]))
priorityQueue_obj.put((1,[2,4]))
priorityQueue_obj.put((1,[2,3]))
while not PriorityQueue_obj.empty():
    print(PriorityQueue_obj.get())
(1, [1, 4])
(1, [2, 3])
(1, [2, 4])
当优先级一样的时候,会在比较数据部分的大小,同上字符串也可以比较大小,
  • 优先级一样,数据部分不可以比较大小
    报错
priorityQueue_obj = PriorityQueue()
priorityQueue_obj.put((1,{"1":9}))   
priorityQueue_obj.put((1,{"k":6}))
priorityQueue_obj.put((1,{"8":9}))
while not priorityQueue_obj.empty():
    print(priorityQueue_obj.get())   # 没有字典不能直接比较大小
# 报错内容
# TypeError: '<' not supported between instances of 'dict' and 'dict'

如果想实现字典这类的比较或者改变其他数据类型的比较大小方式

需要自己实现一个类,将数据包装到类中,在类中自定义或

重写 def __lt__(self, other):魔法方法,其作用是实现同类对象进行“比较”的方法,在类进行比较的时候可以自动调用

class dic:
    def __init__(self,level,data):
        self.level = level
        self.data = data
    def __lt__(self, other):
        if self.level == other.level:
            return len(self.data)<len(other.data)
        return self.level < other.level
priorityQueue_obj = PriorityQueue()
priorityQueue_obj.put(dic(5, {1:4, 2:5}))
priorityQueue_obj.put(dic(4, {1:4}))
priorityQueue_obj.put(dic(5, {1:2}))
while not priorityQueue_obj.empty():
    print(priorityQueue_obj.get().data)
# 结果
{1: 4}
{1: 2}
{1: 4, 2: 5}


如果想避免麻烦,避免出现优先级一样的情况,就省去了一系列的问题


queue.SimpleQueue (3.7 新版功能.)


无界的 FIFO 队列构造函数。简单的队列,缺少任务跟踪等高级功能。


常用方法


  • Queue.qsize()
    返回队列的大致大小。
queue_obj = LifoQueue()  # 创建一个队列对象
for i in range(4):
    queue_obj.put(i)
    print(queue_obj.qsize())
结果
1
2
3
4


Queue.empty()

如果队列为空,返回 True ,否则返回 False 。


Queue.full()

如果队列是满的返回 True ,否则返回 False 。


Queue.put(item, block=True, timeout=None)

将 item 放入队列。如果可选参数 block 是 true 并且 timeout 是 None (默认),则在必要时阻塞至有空闲插槽可用。如果 timeout 是个正数,将最多阻塞 timeout 秒,如果在这段时间没有可用的空闲插槽,将引发 Full 异常。反之 (block 是 false),如果空闲插槽立即可用,则把 item 放入队列,否则引发 Full 异常 ( 在这种情况下,timeout 将被忽略)。


Queue.put_nowait(item)

相当于 put(item, block=False)。


Queue.get(block=True, timeout=None)

从队列中移除并返回一个项目。如果可选参数 block 是 true 并且 timeout 是 None (默认值),则在必要时阻塞至项目可得到。如果 timeout 是个正数,将最多阻塞 timeout 秒,如果在这段时间内项目不能得到,将引发 Empty 异常。反之 (block 是 false) , 如果一个项目立即可得到,则返回一个项目,否则引发 Empty 异常 (这种情况下,timeout 将被忽略)。


Queue.get_nowait()

相当于 get(block=False) 。


Queue.task_done()

在完成一项工作以后,task_done()告诉队列,该任务已处理完成


Queue.join()

阻塞至队列中所有的元素都被接收和处理完毕。

队列添加新工作时,未完成任务的计数就会增一,当调用task_done()函数后,就代表执行完一个工作,未完成任务的计数就会减一,当计数为0时 join() 阻塞被解除。


阻塞与抛出异常


添加元素发生阻塞


queue_obj = Queue(3)  # 队列的最大长度为3
for i in range(4): # 当向队列中添加的元素超过队列的最大长度就会发生阻塞,当队列中取出一个数据才会解除堵塞
    queue_obj.put(i)
    # print(queue_obj.qsize())
print("阻塞")
queue_obj = Queue(3)  # 创建一个队列对象
for i in range(4):
    queue_obj.put(i,block=False)   当超出最大长度的时就会报错


取元素发生阻塞

queue_obj = Queue(3)  
for i in range(3):
    queue_obj.put(i)
for i in range(4):  当取出元素的时候发现没有元素的时候就会发生阻塞
    print(queue_obj.get())
queue_obj = Queue(3)  
for i in range(3):
    queue_obj.put(i)
for i in range(4):  
    print(queue_obj.get(block=False))  如果队列为空,仍然继续取元素,会发生报错


超时报错


queue_obj = Queue(3)  
for i in range(4):
    queue_obj.put(i,timeout=4)  # 如果阻塞4秒,原队列中仍然没有位置,则会发生报错


其他设置tiemout扽同理,只要超出时间,仍然没有解决阻塞,就会抛出异常

相关文章
|
3月前
|
数据采集 存储 安全
如何确保Python Queue的线程和进程安全性:使用锁的技巧
本文探讨了在Python爬虫技术中使用锁来保障Queue(队列)的线程和进程安全性。通过分析`queue.Queue`及`multiprocessing.Queue`的基本线程与进程安全特性,文章指出在特定场景下使用锁的重要性。文中还提供了一个综合示例,该示例利用亿牛云爬虫代理服务、多线程技术和锁机制,实现了高效且安全的网页数据采集流程。示例涵盖了代理IP、User-Agent和Cookie的设置,以及如何使用BeautifulSoup解析HTML内容并将其保存为文档。通过这种方式,不仅提高了数据采集效率,还有效避免了并发环境下的数据竞争问题。
如何确保Python Queue的线程和进程安全性:使用锁的技巧
|
6月前
|
安全
python_threading多线程、queue安全队列
python_threading多线程、queue安全队列
56 2
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 09. 用两个栈实现队列
使用两个栈实现队列的Python解决方案,包括初始化两个栈、实现在队列尾部添加整数的appendTail方法和在队列头部删除整数的deleteHead方法,以及相应的示例操作。
39 2
|
3月前
|
数据采集 Java Python
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
|
4月前
|
数据采集 Python
Python多进程:如何在不依赖Queue的情况下传递结果
本文探讨了在Python中使用多进程技术采集抖音短视频数据时,如何在不依赖队列(Queue)的情况下传递结果。文章首先介绍了多进程提高数据采集效率的背景,然后指出了队列在处理大量数据时可能成为性能瓶颈,并增加了系统复杂性。作为解决方案,提出了使用管道、共享内存和临时文件等替代方法。文章通过一个实战案例,详细演示了如何配置爬虫代理、设置请求头、实现定时器装饰器、抓取视频数据以及通过管道在子进程间传递结果。最后,文章总结了使用这些替代方案可以有效提高数据采集的效率和可靠性。
Python多进程:如何在不依赖Queue的情况下传递结果
|
3月前
|
Python
【python】】Python 的 queue 模块使用笔记
【python】】Python 的 queue 模块使用笔记
41 0
|
3月前
|
前端开发 Python
数据结构Python用队列实现杨辉三角形
数据结构Python用队列实现杨辉三角形
34 0
|
3月前
|
Python
[Python]队列基础
[Python]队列基础
|
3月前
|
Python
【Leetcode刷题Python】641.循环双端队列
文章介绍了如何实现一个循环双端队列,包括其操作如插入、删除、获取队首和队尾元素,以及检查队列是否为空或已满,并提供了Python语言的实现代码。
23 0
|
3月前
|
Python
【Leetcode刷题Python】232. 用栈实现队列
如何使用Python语言通过两个栈来实现队列的所有基本操作,包括入队(push)、出队(pop)、查看队首元素(peek)和判断队列是否为空(empty),并提供了相应的代码实现。
21 0