python queue_Python-Queue 入门
Queue 簡介
Queue 叫隊列,是數(shù)據(jù)結(jié)構(gòu)中的一種,基本上所有成熟的編程語言都內(nèi)置了對 Queue 的支持。
Python 中的 Queue 模塊實現(xiàn)了多生產(chǎn)者和多消費者模型,當(dāng)需要在多線程編程中非常實用。而且該模塊中的 Queue 類實現(xiàn)了鎖原語,不需要再考慮多線程安全問題
該模塊內(nèi)置了三種類型的 Queue,分別是class queue.Queue(maxsize=0),class queue.LifoQueue(maxsize=0)和class queue.PriorityQueue(maxsize=0)。它們?nèi)齻€的區(qū)別僅僅是取出時的順序不一致而已。
Queue 是一個 FIFO 隊列,任務(wù)按照添加的順序被取出。
LifoQueue 是一個 LIFO 隊列,類似堆棧,后添加的任務(wù)先被取出。
PriorityQueue 是一個優(yōu)先級隊列,隊列里面的任務(wù)按照優(yōu)先級排序,優(yōu)先級高的先被取出。
Queue 常用操作
類和異常
1 class queue.Queue(maxsize=0)2 class queue.LifoQueue(maxsize=0)3 class queue.PriorityQueue(maxsize=0)
如你所見,就是上面所說的三種不同類型的內(nèi)置隊列,其中 maxsize 是個整數(shù),用于設(shè)置可以放入隊列中的任務(wù)數(shù)的上限。當(dāng)達到這個大小的時候,插入操作將阻塞至隊列中的任務(wù)被消費掉。如果 maxsize 小于等于零,則隊列尺寸為無限大。
1 exception queue.Empty2 #對空的 Queue 對象調(diào)用非阻塞的 get() (or get_nowait()) 時,會引發(fā)該異常。
3
4 exception queue.Full5 #對滿的 Queue 對象調(diào)用非阻塞的 put() (or put_nowait()) 時,會引發(fā)該異常。
常用操作
添加任務(wù)
向隊列中添加任務(wù),直接調(diào)用put()函數(shù)即可
1 importqueue2 >>> q = queue.Queue(maxsize=1)3 >>> q.put(100)
put()函數(shù)完整的函數(shù)簽名如下Queue.put(item, block=True, timeout=None),如你所見,該函數(shù)有兩個可選參數(shù)。
默認(rèn)情況下,在隊列滿時,該函數(shù)會一直阻塞,直到隊列中有空余的位置可以添加任務(wù)為止。如果 timeout 是正數(shù),則最多阻塞 timeout 秒,如果這段時間內(nèi)還沒有空余的位置出來,則會引發(fā)Full異常。
1 >>> importqueue2 >>> q = queue.Queue(maxsize=1)3 >>> q.put(100)4 >>> q.put(100,True,2)5 Traceback (most recent call last):6 File "", line 1, in
7 File "E:\Python37-32\lib\queue.py", line 147, input8 raiseFull9 queue.Full #創(chuàng)建一個容量為 1 的隊列,2 秒內(nèi)沒有位置添加任務(wù)則引發(fā) Full 異常
10 >>> q.put(100) #該方法會一直阻塞
當(dāng) block 為 false 時,timeout 參數(shù)將失效。同時如果隊列中沒有空余的位置可添加任務(wù)則會引發(fā)Full異常,否則會直接把任務(wù)放入隊列并返回,不會阻塞。
1 >>> importqueue2 >>> q = queue.Queue(maxsize=1)3 >>> q.put(100)4 >>> q.put(100,False,2)5 Traceback (most recent call last):6 File "", line 1, in
7 File "E:\Python37-32\lib\queue.py", line 136, input8 raiseFull9 queue.Full10 #創(chuàng)建一個容量為 1 的隊列,在第二次放入任務(wù)時指定為非阻塞模式,則會立刻引發(fā) Full 異常
另外,還可以通過Queue.put_nowait(item)來添加任務(wù),相當(dāng)于Queue.put(item, False),不再贅述。同樣,在隊列滿時,該操作會引發(fā)Full異常。
獲取任務(wù)
從隊列中獲取任務(wù),直接調(diào)用get()函數(shù)即可
1 >>> importqueue2 >>> q =queue.Queue()3 >>> q.put(100)4 >>>q.get()5 100
與put()函數(shù)一樣,get()函數(shù)也有兩個可選參數(shù),完整簽名如下Queue.get(block=True, timeout=None)。
默認(rèn)情況下,當(dāng)隊列空時調(diào)用該函數(shù)會一直阻塞,直到隊列中有任務(wù)可獲取為止。如果 timeout 是正數(shù),則最多阻塞 timeout 秒,如果這段時間內(nèi)還沒有任務(wù)可獲取,則會引發(fā)Empty異常。
1 >>> importqueue2 >>> q =queue.Queue()3 >>> q.put(100)4 >>>q.get()5 100
6 >>> q.get(True,2)7 Traceback (most recent call last):8 File "", line 1, in
9 File "E:\Python37-32\lib\queue.py", line 178, inget10 raiseEmpty11 _queue.Empty #2 秒鐘內(nèi)沒有任務(wù)可獲取則引發(fā) Empty 異常
12 >>> q.get() #該方法會一直阻塞
當(dāng) block 為 false 時,timeout 參數(shù)將失效。同時如果隊列中沒有任務(wù)可獲取則會立刻引發(fā)Empty異常,否則會直接獲取一個任務(wù)并返回,不會阻塞。
1 >>> importqueue2 >>> q =queue.Queue()3 >>> q.put(100)4 >>>q.get()5 100
6 >>> q.get(False,2)7 Traceback (most recent call last):8 File "", line 1, in
9 File "E:\Python37-32\lib\queue.py", line 167, inget10 raiseEmpty11 _queue.Empty12 #指定為非阻塞模式,隊列為空則立即引發(fā) Empty 異常
另外,還可以通過Queue.get_nowait()來獲取任務(wù),相當(dāng)于Queue.get(False),不再贅述。同樣,在隊列為空時,該操作會引發(fā)Empty異常。
其他常用方法
獲取隊列大小
1 >>> importqueue2 >>> q =queue.Queue()3 >>> q.put(100)4 >>> q.put(200)5 >>>q.qsize()6 2
判斷隊列是否空
如果隊列為空,返回True,否則返回False。如果 empty() 返回True,不保證后續(xù)調(diào)用的 put() 不被阻塞。類似的,如果 empty() 返回False,也不保證后續(xù)調(diào)用的 get() 不被阻塞。
判斷隊列是否滿
如果隊列是滿的返回True,否則返回False。如果 full() 返回True不保證后續(xù)調(diào)用的 get() 不被阻塞。類似的,如果 full() 返回False也不保證后續(xù)調(diào)用的 put() 不被阻塞。
1 >>> importqueue2 >>> q = queue.Queue(maxsize=1)3 >>>q.empty()4 True5 >>>q.full()6 False7 >>> q.put(100)8 >>>q.empty()9 False10 >>>q.full()11 True
隊列對比
FIFO 隊列
queue.Queue()是 FIFO 隊列,出隊順序跟入隊順序是一致的。
1 importqueue2 q =queue.Queue()3 for index in range(10):4 q.put(index)5 while notq.empty():6 print(q.get(), end=",")7 ## 輸出結(jié)果如下
8 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
LIFO 隊列
queue.LifoQueue()是 LIFO 隊列,出隊順序跟入隊順序是完全相反的,類似于棧。
importqueue
q= queue.LifoQueue() #創(chuàng)建一個 LIFO 隊列
for index in range(10):
q.put(index)while notq.empty():print(q.get(), end=",")## 輸出結(jié)果如下
9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
優(yōu)先級隊列
優(yōu)先級隊列中的任務(wù)順序跟放入時的順序是無關(guān)的,而是按照任務(wù)的大小來排序,最小值先被取出。那任務(wù)比較大小的規(guī)則是怎么樣的呢。
如果是內(nèi)置類型,比如數(shù)值或者字符串,則按照自然順序來比較排序。
importqueue
q=queue.PriorityQueue()for index in range(10,0,-1):
q.put(index)while notq.empty():print(q.get(), end=",")## 輸出結(jié)果如下
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
如果是列表或者元祖,則先比較第一個元素,然后比較第二個,以此類推,直到比較出結(jié)果
importqueue
q=queue.PriorityQueue()
q.put(["d","b"])
q.put(["c","b"])while notq.empty():print(q.get(), end=",")## 輸出結(jié)果如下
['c', 'b'], ['d', 'b'],
注意,因為列表的比較對規(guī)則是按照下標(biāo)順序來比較的,所以在沒有比較出大小之前 ,隊列中所有列表對應(yīng)下標(biāo)位置的元素類型要一致。
好比[2,1]和["1","b"]因為第一個位置的元素類型不一樣,所以是沒有辦法比較大小的,所以也就放入不了優(yōu)先級隊列。
然而對于[2,1]和[1,"b"]來說即使第二個元素的類型不一致也是可以放入優(yōu)先級隊列的,因為只需要比較第一個位置元素的大小就可以比較出結(jié)果了,就不需要比較第二個位置元素的大小了。
但是對于[2,1]和 1[2,"b"]來說,則同樣不可以放入優(yōu)先級隊列,因為需要比較第二個位置的元素才可以比較出結(jié)果,然而第二個位置的元素類型是不一致的,無法比較大小。
綜上,也就是說,直到在比較出結(jié)果之前,對應(yīng)下標(biāo)位置的元素類型都是需要一致的。
如果是自定義類型,需要實現(xiàn)__lt__比較函數(shù)
下面我們自定義一個動物類型,希望按照年齡大小來做優(yōu)先級排序。年齡越小優(yōu)先級越高。
importqueue
q=queue.PriorityQueue()classAnimal:def __init__(self, age, name):
self.age=age
self.name=namedef __lt__(self, other): #實現(xiàn) < 操作
return self.age < other.age #如果將 < 變成 > 則相當(dāng)于逆序
q.put(Animal(3,"cat"))
q.put(Animal(2,"dog"))while notq.empty():
animal=q.get()print(animal.name, animal.age, end=",")## 輸出結(jié)果如下
dog 2, cat 3,
總結(jié)
以上是生活随笔為你收集整理的python queue_Python-Queue 入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 文件大小_linux系统中查
- 下一篇: python3 requests 动态网