Модуль queue в Python
В Python,queueмодуль предоставляет потокобезопасную реализацию очереди для безопасной передачи данных в многопоточном программировании.
Очередь — это структура данных, работающая по принципу «первым пришёл — первым вышел» (FIFO),queueмодуль предоставляет несколько типов очередей, включаяQueue、LifoQueueиPriorityQueue, чтобы удовлетворить различные потребности.
Типы очередей
1. Queue
QueueДаqueueНаиболее часто используемый тип очереди в модуле, реализующий стандартную очередь FIFO (first-in, first-out). Далее следуетQueueбазовое использование:
Пример
# Создать очередь
q = queue.Queue()
# Добавить элементы в очередь
q.put(1)
q.put(2)
q.put(3)
# Получить элементы из очереди
print(q.get()) # Вывод: 1
print(q.get()) # Вывод: 2
print(q.get()) # Вывод: 3
2. LifoQueue
LifoQueueпредставляет собой LIFO-очередь (последним пришёл — первым вышел), похожую на стек. Далее следуетLifoQueueбазовое использование:
Пример
# Создать LIFO-очередь
q = queue.LifoQueue()
# Добавить элементы в очередь
q.put(1)
q.put(2)
q.put(3)
# Получить элементы из очереди
print(q.get()) # Вывод: 3
print(q.get()) # Вывод: 2
print(q.get()) # Вывод: 1
3. PriorityQueue
PriorityQueueпредставляет собой очередь с приоритетом, в которой элементы извлекаются в порядке приоритета. Далее следуетPriorityQueueбазовое использование:
Пример
# Создать очередь с приоритетом
q = queue.PriorityQueue()
# Добавить элементы в очередь, элементы — кортежи (priority, data)
q.put((3, 'Низкий приоритет'))
q.put((1, 'Высокий приоритет'))
q.put((2, 'Средний приоритет'))
# Получить элементы из очереди
print(q.get()) # Вывод: (1, 'High priority')
print(q.get()) # Вывод: (2, 'Medium priority')
print(q.get()) # Вывод: (3, 'Low priority')
Общие методы
1. put(item, block=True, timeout=None)
будетitemПоместить в очередь. ЕслиblockявляетсяTrueи очередь заполнена, подождатьtimeoutсекунд, пока в очереди не появится свободное место. ЕслиtimeoutявляетсяNone, то ждать бесконечно.
2. get(block=True, timeout=None)
Получить и удалить элемент из очереди. ЕслиblockявляетсяTrueи очередь пуста, подождатьtimeoutсекунд, пока в очереди не появится элемент. ЕслиtimeoutявляетсяNone, то ждать бесконечно.
3. qsize()
Вернуть количество элементов в очереди.
4. empty()
Если очередь пуста, вернутьTrue, иначе returnFalse。
5. full()
Если очередь заполнена, вернутьTrue, иначе returnFalse。
Потокобезопасность
queueВсе типы очередей модуля потокобезопасны, что означает, что несколько потоков могут безопасно работать с одной и той же очередью одновременно без дополнительных механизмов синхронизации. Это делаетqueueмодуль идеальным выбором для передачи данных в многопоточном программировании.
Пример: многопоточная очередь
Ниже приведен пример использованияQueueдля передачи данных между несколькими потоками:
Пример
import threading
import time
# Создать очередь
q = queue.Queue()
# Поток производителя
def producer():
for i in range(5):
print(f'Produce {i}')
q.put(i)
time.sleep(1)
# Поток потребителя
def consumer():
while True:
item = q.get()
if item is None:
break
print(f'Consume {item}')
q.task_done()
# Запустить поток производителя
producer_thread = threading.Thread(target=producer)
producer_thread.start()
# Запустить поток потребителя
consumer_thread = threading.Thread(target=consumer)
consumer_thread.start()
# Дождаться завершения потока производителя
producer_thread.join()
# Дождаться завершения всех задач в очереди
q.join()
# Отправить сигнал завершения
q.put(None)
consumer_thread.join()
Общие атрибуты и методы
Ниже представлено табличное описание общих классов, методов и атрибутов модуля queue в Python (потокобезопасная очередь), включая описания функций и примеры:
Основные классы модуля queue
| Класс | Описание | Применимые сценарии |
|---|---|---|
queue.Queue | Очередь FIFO (первым пришёл — первым вышел) | Очередь задач общего назначения |
queue.LifoQueue | Очередь LIFO (последним пришёл — первым вышел) (похожа на стек) | Сценарии, требующие порядок «последним пришёл — первым вышел» |
queue.PriorityQueue | Приоритетная очередь (реализация на минимальной куче) | Обработка задач по приоритету |
queue.SimpleQueue | Более простая очередь FIFO (Python 3.7+) | Сценарии, не требующие расширенных возможностей |
Общие методы (поддерживаются всеми классами очередей)
| Метод | Описание | Пример | Возвращаемое значение |
|---|---|---|---|
put(item) | Поместить элемент | q.put("task1") | Отсутствует |
get() | Получить и удалить элемент | item = q.get() | Элемент очереди |
empty() | Проверить, пуста ли очередь | if q.empty(): | True/False |
full() | Проверить, заполнена ли очередь | if q.full(): | True/False |
qsize() | Вернуть текущий размер очереди | size = q.qsize() | Integer |
task_done() | Отметить завершение задачи (используется дляjoin()) | q.task_done() | Отсутствует |
join() | блокировки до завершения всех задач | q.join() | Отсутствует |
Параметры управления блокировкой
| Параметр | Описание | Значение по умолчанию | Пример |
|---|---|---|---|
block | Блокировать ли, когда очередь пуста/полна | True | q.get(block=False) |
timeout | Тайм-аут блокировки (секунды) | None | q.put(x, timeout=5) |
Особенности использования PriorityQueue
Формат элемента:(priority, data), чем меньше приоритет, тем раньше он извлекается из очереди
Пример
pq.put((1, "low"))
pq.put((0, "high"))
print(pq.get()[1]) # Вывод: "high"
Пример
Модель производитель-потребитель:
Пример
q = queue.Queue(maxsize=3) # Очередь с вместимостью 3
def producer():
for i in range(5):
q.put(f"Task-{i}")
print(f"Produced: Task-{i}")
def consumer():
while True:
item = q.get()
print(f"Consumed: {item}")
q.task_done()
threading.Thread(target=producer, daemon=True).start()
threading.Thread(target=consumer, daemon=True).start()
q.join() # Дождаться завершения всех задач
Обработка задач с приоритетом:
Пример
pq.put((3, "Scan"))
pq.put((1, "Emergency"))
pq.put((2, "Log"))
while not pq.empty():
print(pq.get()[1]) # Порядок вывода: Emergency → Log → Scan
Неблокирующее получение (во избежание взаимоблокировки):
Пример
item = q.get_nowait() # Эквивалентно q.get(block=False)
except queue.Empty:
print("Очередь пуста")