Spec-Zone.ru › Python 3.8

queue — Класс синхронизированной очереди

Исходный код: Lib/queue.py

Модуль queue реализует очереди с множеством производителей и потребителей. Он особенно полезен в многопоточной программировании, когда информация должна безопасно обмениваться между несколькими потоками. Класс Queue в этом модуле реализует всю необходимую семантику блокировки.

Модуль реализует три типа очереди, которые отличаются только порядком извлечения элементов. В очереди FIFO первыми извлекаются те задачи, которые были добавлены первыми. В очереди LIFO первым извлекается последний добавленный элемент (работает как стек). В очереди с приоритетами элементы хранятся в отсортированном виде (используя модуль heapq) и первым извлекается элемент с наименьшим значением.

Внутренне эти три типа очередей используют блокировки для временного блокирования конкурирующих потоков; однако они не предназначены для обработки повторного входа в поток.

Кроме того, модуль реализует «простой» тип очереди FIFO, SimpleQueue, чья реализация обеспечивает дополнительные гарантии в обмен на меньший функционал.

Модуль queue определяет следующие классы и исключения:

class queue.Queue(maxsize=0)

Конструктор для очереди FIFO. maxsize — целое число, которое устанавливает верхнюю границу количества элементов, которые можно поместить в очередь. Вставка заблокируется, как только этот размер будет достигнут, до тех пор, пока элементы очереди не будут извлечены. Если maxsize меньше или равно нулю, размер очереди бесконечен.

class queue.LifoQueue(maxsize=0)

Конструктор для очереди LIFO. maxsize — целое число, которое устанавливает верхнюю границу количества элементов, которые можно поместить в очередь. Вставка заблокируется, как только этот размер будет достигнут, до тех пор, пока элементы очереди не будут извлечены. Если maxsize меньше или равно нулю, размер очереди бесконечен.

class queue.PriorityQueue(maxsize=0)

Конструктор для очереди с приоритетами. maxsize — целое число, которое устанавливает верхнюю границу количества элементов, которые можно поместить в очередь. Вставка заблокируется, как только этот размер будет достигнут, до тех пор, пока элементы очереди не будут извлечены. Если maxsize меньше или равно нулю, размер очереди бесконечен.

Элементы с наименьшим значением извлекаются первыми (элемент с наименьшим значением — это тот, который возвращает sorted(list(entries))[0]). Типичный шаблон для элементов — кортеж в формате: (priority_number, data).

Если элементы data не сравнимы, данные можно обернуть в класс, который игнорирует элемент данных и сравнивает только номер приоритета:

from dataclasses import dataclass, field
from typing import Any

@dataclass(order=True)
class PrioritizedItem:
    priority: int
    item: Any=field(compare=False)
class queue.SimpleQueue

Конструктор для неограниченной очереди FIFO. Простые очереди лишены расширенного функционала, такого как отслеживание задач.

Добавлен в версии 3.7.

exception queue.Empty

Исключение, генерируемое при вызове get() (или get_nowait()) без блокировки для объекта Queue, который пуст.

exception queue.Full

Исключение, генерируемое при вызове put() (или put_nowait()) без блокировки для объекта Queue, который заполнен.

Объекты очереди

Объекты очереди (Queue, LifoQueue или PriorityQueue) предоставляют описанные ниже общедоступные методы.

Queue.qsize()

Возвращает приблизительный размер очереди. Обратите внимание, что qsize() > 0 не гарантирует, что последующий get() не будет заблокирован, а qsize() < maxsize не гарантирует, что put() не будет заблокирован.

Queue.empty()

Возвращает True если очередь пуста, False в противном случае. Если empty() возвращает True это не гарантирует, что последующий вызов put() не заблокируется. Аналогично, если empty() возвращает False это не гарантирует, что последующий вызов get() не заблокируется.

Queue.full()

Возвращает True если очередь полна, False в противном случае. Если full() возвращает True это не гарантирует, что последующий вызов get() не заблокируется. Аналогично, если full() возвращает False это не гарантирует, что последующий вызов put() не заблокируется.

Queue.put(item, block=True, timeout=None)

Поместить item в очередь. Если необязательные аргументы block равны true и timeout равен None (по умолчанию), заблокировать, если необходимо, пока не появится свободное место. Если timeout — положительное число, то блокировка длится не более timeout секунд, и вызывается исключение Full, если свободного места не появилось в течение этого времени. В противном случае (block равно false), поместить элемент в очередь, если свободное место доступно немедленно, иначе вызывается исключение Full (timeout игнорируется в этом случае).

Queue.put_nowait(item)

Эквивалентно put(item, False).

Queue.get(block=True, timeout=None)

Удалить и вернуть элемент из очереди. Если необязательные аргументы block равны true и timeout равен None (по умолчанию), заблокировать, если необходимо, пока элемент не станет доступен. Если timeout — положительное число, то блокировка длится не более timeout секунд, и вызывается исключение Empty, если элемент не был доступен в течение этого времени. В противном случае (block равно false), вернуть элемент, если он доступен немедленно, иначе вызывается исключение Empty (timeout игнорируется в этом случае).

До версии 3.0 на системах POSIX и во всех версиях на Windows, если block равно true и timeout равно None, эта операция переходит в непрерывающий ожидание на базовой блокировке. Это означает, что исключения не могут произойти, и в частности, SIGINT не вызовет KeyboardInterrupt.

Queue.get_nowait()

Эквивалентно get(False).

Предлагаются два метода для отслеживания того, были ли задачи, помещенные в очередь, полностью обработаны демоновыми потоками-потребителями.

Queue.task_done()

Указывает, что задача, ранее помещенная в очередь, завершена. Используется потоками-потребителями очереди. Для каждого вызова get() для получения задачи, последующий вызов task_done() сообщает очереди, что обработка задачи завершена.

Если join() в настоящее время заблокирован, он возобновится, когда все элементы будут обработаны (что означает, что вызов task_done() был получен для каждого элемента, который был put() в очередь).

Вызывает ValueError, если вызван большее количество раз, чем было помещено элементов в очередь.

Queue.join()

Блокируется, пока все элементы в очереди не будут извлечены и обработаны.

Счет незавершенных задач увеличивается всякий раз, когда элемент добавляется в очередь. Счет уменьшается всякий раз, когда поток-потребитель вызывает task_done() для указания того, что элемент был извлечен и вся работа над ним завершена. Когда счет незавершенных задач уменьшается до нуля, join() разблокируется.

Пример того, как дождаться завершения задач в очереди:

import threading, queue

q = queue.Queue()

def worker():
    while True:
        item = q.get()
        print(f'Working on {item}')
        print(f'Finished {item}')
        q.task_done()

# turn-on the worker thread
threading.Thread(target=worker, daemon=True).start()

# send thirty task requests to the worker
for item in range(30):
    q.put(item)
print('All task requests sent\n', end='')

# block until all tasks are done
q.join()
print('All work completed')

Объекты SimpleQueue

SimpleQueue предоставляют описанные ниже публичные методы.

SimpleQueue.qsize()

Возвращает приблизительный размер очереди. Обратите внимание, что qsize() > 0 не гарантирует, что последующий вызов get() не заблокируется.

SimpleQueue.empty()

Возвращает True , если очередь пуста, и False в противном случае. Если empty() возвращает False, это не гарантирует, что последующий вызов get() не заблокируется.

SimpleQueue.put(item, block=True, timeout=None)

Поместить item в очередь. Метод никогда не блокируется и всегда выполняется успешно (кроме потенциальных ошибок низкого уровня, таких как неудача в выделении памяти). Дополнительные аргументы block и timeout игнорируются и предоставляются только для совместимости с Queue.put().

Подробность реализации CPython: Этот метод имеет реализацию на C, которая является реентерабельной. То есть вызов put() или get() может быть прерван другим вызовом put() в том же потоке без возникновения тупика или повреждения внутреннего состояния внутри очереди. Это делает его подходящим для использования в деструкторах, таких как методы __del__ или weakref обратные вызовы.

SimpleQueue.put_nowait(item)

Эквивалентно put(item), предоставляется для совместимости с Queue.put_nowait().

SimpleQueue.get(block=True, timeout=None)

Удалить и вернуть элемент из очереди. Если необязательный аргумент block равен true и timeout равен None (по умолчанию), заблокировать, если необходимо, до тех пор, пока элемент не станет доступен. Если timeout является положительным числом, блокировка происходит не более timeout секунд, и если элемент не был доступен в течение этого времени, генерируется исключение Empty. В противном случае (block ложно), вернуть элемент, если он сразу доступен, иначе сгенерировать исключение Empty (timeout игнорируется в этом случае).

SimpleQueue.get_nowait()

Эквивалентно get(False).

См. также

Class multiprocessing.Queue

Класс очереди для использования в контексте многопроцессорной (а не многопоточной) обработки.

collections.deque — альтернативная реализация неограниченных очередей с быстрыми атомными операциями append() и popleft(), которые не требуют блокировки, а также поддерживают индексирование.

© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/queue.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API