本篇 ShengYu 將介紹如何使用 Python Queue 用法與範例,Python Queue 是實作 multi-producer multi-consumer queue,適用於多執行緒中的資訊交換。Queue 在 Python 2 和 Python 3 的 import 不一樣,Python 2 是 import Queue
,Python 3 是 import queue
,本篇以 Python 3 為主,Python 提供了三種 Queue,分別為
- queue.Queue:FIFO 先進先出
- queue.LifoQueue:LIFO類似於堆疊 stack,即先進後出
- queue.PriorityQueue:優先級別越低越先出來
本篇介紹基本的 Queue 先進先出。
Queue 的常用的成員函式有以下,Queue.qsize()
:返回 Queue 的大小Queue.empty()
:如果 Queue 為空,返回 True,反之返回 FalseQueue.full()
:如果 Queue 滿了,返回 True,反之返回 FalseQueue.get([block[, timeout]])
:取出 Queue,timeout 可以指定等待時間Queue.get_nowait()
:等於 Queue.get(False)Queue.put(item)
:放入 Queue,timeout 可以指定等待時間Queue.put_nowait(item)
:等於 Queue.put(item, False)Queue.task_done()
:在完成一項工作之後,Queue.task_done() 向任務已經完成的 Queue 發送一個訊號Queue.join()
:等待直到 Queue 為空,再繼續執行
Queue 的放入與取出
Queue 放入是使用 put()
,取出是 get()
,以下面的例子來說,放出 3 個元素後,再取出 3 個元素,這時 Queue 裡面是空的狀態。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import queue
q = queue.Queue()
q.put(1)
q.put(2)
q.put(3)
print(q.empty())
print(q.get())
print(q.get())
print(q.get())
print(q.empty())
輸出如下,1
2
3
4
5False
1
2
3
True
Queue 放入各種變數類型
Queue 可以放入各種變數類型,整數、浮點數、字串或其它類型。1
2
3
4
5
6
7
8
9
10
11
12
13#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from queue import Queue
q = Queue()
q.put('hello')
q.put('world')
q.put(123)
print(q.get())
print(q.get())
print(q.get())
輸出如下,1
2
3hello
world
123
設定 Queue 的 maxsize
在 Queue 初始化時可以傳入 maxsize 來設定 Queue 的上限,以下示範設定 Queue 上限為 3。1
2
3
4
5
6
7
8
9
10
11
12#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from queue import Queue
q = Queue(maxsize=3)
for i in range(5):
q.put(i)
print('put ' + str(i))
while not q.empty():
print(q.get())
輸出如下,發現在第 4 次 put 時卡住,1
2
3put 0
put 1
put 2
原因是因為我們限制 maxsize 為 3,滿了之後要 put 會 block 卡住,
改成 q.put(i, block=False) 的話就不會 block 但要自行 ,因為內部會 raise Full,這邊就不示範了。另外使用 q.put(block=False)
與 q.put_nowait()
,q.get()
也有對應的 q.get_nowait()
。
Queue 達到上限時可以針對當下需求作變化,有些情況是用丟棄舊元素保留最新元素,作法就是判斷 Queue 滿了就取出一些舊元素,1
2
3while queue.qsize() > 3:
queue.get(block=False)
queue.put(i)
有些情況則是用丟棄最新元素包留舊元素,作法就是判斷 Queue 沒滿才放入新元素,1
2if queue.qsize() < 3:
queue.put(i)
在多執行緒裡使用 Queue
在設計模式(design pattern)中,這是一個典型的生產者與消費者(producer-consumer)的例子,
範例裡有一位生產者 producer 每 2 秒生產了 1 個東西放到 Queue 裡,當 Queue 達到上限 10 的話 producer 就跳過這次不放東西進 Queue 裡,Queue 達到上限滿了要跳過不放入還是 block 等待直到 Queue 有空位,完全取決於當下的情況作設計,這邊只作簡單的示範,
另外有一位消費者 consumer 的會每隔1秒來取貨作後續的事情,當 Queue 空的話就跳過這次不取出東西。
Python 的 Queue 是 thread safe,Queue 的內部已經有實作 Condition 與 Lock 保護臨界區,所以在多執行緒中使用 Queue 可以不用自己上鎖。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import queue
import time
import random
import threading
q = queue.Queue(10)
class Producer(threading.Thread):
def __init__(self, thread_name):
super(Producer, self).__init__(name=thread_name)
def run(self):
global q
count = 1
while True:
if q.full():
print('queue is full')
pass
else:
msg = str(count)
q.put(msg)
print(self.name + ' put ' + msg + ', qsize: ' + str(q.qsize()))
count=count+1
time.sleep(2)
#time.sleep(random.random())
class Consumer(threading.Thread):
def __init__(self, thread_name):
super(Consumer, self).__init__(name=thread_name)
def run(self):
global q
while True:
if q.empty():
print('queue is empty')
pass
else:
msg=q.get()
print(self.name + ' get ' + msg + ', qsize: ' + str(q.qsize()))
time.sleep(1)
p = Producer('producer')
p.start()
c = Consumer('consumer')
c.start()
輸出如下,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17producer put 1, qsize: 1
consumer get 1, qsize: 0
queue is empty
queue is empty
producer put 2, qsize: 1
consumer get 2, qsize: 0
producer put 3, qsize: 1
consumer get 3, qsize: 0
queue is empty
producer put 4, qsize: 1
consumer get 4, qsize: 0
queue is empty
producer put 5, qsize: 1
consumer get 5, qsize: 0
queue is empty
producer put 6, qsize: 1
consumer get 6, qsize: 0
以上就是 Python Queue 用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!
其它參考
queue — A synchronized queue class — Python 3 documentation
https://docs.python.org/3.7/library/queue.html
其它相關文章推薦
如果你想學習 Python 相關技術,可以參考看看下面的文章,
Python 新手入門教學懶人包