Python Queue 用法與範例

本篇 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,反之返回 False
Queue.full():如果 Queue 滿了,返回 True,反之返回 False
Queue.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 裡面是空的狀態。

python3-queue.py
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
5
False
1
2
3
True

Queue 放入各種變數類型

Queue 可以放入各種變數類型,整數、浮點數、字串或其它類型。

python3-queue2.py
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
3
hello
world
123

設定 Queue 的 maxsize

在 Queue 初始化時可以傳入 maxsize 來設定 Queue 的上限,以下示範設定 Queue 上限為 3。

python3-queue3.py
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
3
put 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
3
while queue.qsize() > 3:
queue.get(block=False)
queue.put(i)

有些情況則是用丟棄最新元素包留舊元素,作法就是判斷 Queue 沒滿才放入新元素,

1
2
if 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 可以不用自己上鎖。

python3-queue4.py
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
17
producer 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 新手入門教學懶人包