Модуль queue в Python

В Python,queueмодуль предоставляет потокобезопасную реализацию очереди для безопасной передачи данных в многопоточном программировании.

Очередь — это структура данных, работающая по принципу «первым пришёл — первым вышел» (FIFO),queueмодуль предоставляет несколько типов очередей, включаяQueue、LifoQueueиPriorityQueue, чтобы удовлетворить различные потребности.


Типы очередей

1. Queue

QueueДаqueueНаиболее часто используемый тип очереди в модуле, реализующий стандартную очередь FIFO (first-in, first-out). Далее следуетQueueбазовое использование:

Пример

import 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базовое использование:

Пример

import queue

# Создать 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базовое использование:

Пример

import queue

# Создать очередь с приоритетом
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 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Блокировать ли, когда очередь пуста/полнаTrueq.get(block=False)
timeoutТайм-аут блокировки (секунды)Noneq.put(x, timeout=5)

Особенности использования PriorityQueue

Формат элемента:(priority, data), чем меньше приоритет, тем раньше он извлекается из очереди

Пример

pq = queue.PriorityQueue()
pq.put((1, "low"))
pq.put((0, "high"))
print(pq.get()[1])  # Вывод: "high"

Пример

Модель производитель-потребитель:

Пример

import queue, threading

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 = queue.PriorityQueue()
pq.put((3, "Scan"))
pq.put((1, "Emergency"))
pq.put((2, "Log"))

while not pq.empty():
    print(pq.get()[1])  # Порядок вывода: Emergency → Log → Scan

Неблокирующее получение (во избежание взаимоблокировки):

Пример

try:
    item = q.get_nowait()  # Эквивалентно q.get(block=False)
except queue.Empty:
    print("Очередь пуста")
Другие расширения