python / 3.7.2rc1 / all / library-queue.html

queue —同步队列类

源代码: Lib/queue.py


queue模块实现多生产者,多 Consumer 队列。当必须在多个线程之间安全地交换信息时,它在线程编程中特别有用。此模块中的Queue类实现所有必需的锁定语义。

该模块实现了三种类型的队列,它们的区别仅在于检索条目的 Sequences 不同。在 FIFO 队列中,首先检索到添加的第一个任务。在 LIFO 队列中,最近添加的条目是第一个检索到的条目(操作类似于堆栈)。使用优先级队列,条目将保持排序(使用heapq模块),并首先检索值最低的条目。

在内部,这三种类型的队列使用锁来临时阻止竞争线程。但是,它们并非旨在处理线程内的重入。

另外,该模块实现了“简单” FIFO 队列类型SimpleQueue,其特定实现为交换较小的Function提供了额外的保证。

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)形式的 Tuples。

如果* data *元素不可比较,则可以将数据包装在忽略数据项并且仅比较优先级数字的类中:

from dataclasses import dataclass, field
from typing import Any

@dataclass(order=True)
class PrioritizedItem:
    priority: int
    item: Any=field(compare=False)
  • 类别 queue. SimpleQueue
    • 无限 FIFO 队列的构造函数。简单的队列缺少诸如任务跟踪之类的高级Function。

3.7 版中的新Function。

Queue Objects

队列对象(QueueLifoQueuePriorityQueue)提供下面描述的公共方法。

  • 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 *放入队列。如果可选参数 args * block 为 true 且 timeout None(默认值),则在必要时进行阻塞,直到有可用的插槽可用为止。如果 timeout 是一个正数,则它最多会阻塞 timeout 秒,并且如果在这段时间内没有可用的可用插槽,则会引发Full异常。否则( block 为 false),如果有空闲插槽可立即使用,则将一项放在队列中,否则引发Full异常(在这种情况下, timeout *被忽略)。
  • Queue. put_nowait(* item *)

    • 等效于put(item, False)
  • Queue. get(* block = True timeout = None *)

    • 从队列中删除并返回一个项目。如果可选参数 args * block 为 true 且 timeout None(默认值),则如有必要,请阻塞直到有可用项为止。如果 timeout 是一个正数,则它最多会阻塞 timeout 秒,如果在该时间内没有可用项,则会引发Empty异常。否则( block 为 false),如果有一个立即可用,则返回一个项目,否则引发Empty异常(在这种情况下, timeout *被忽略)。

在 POSIX 系统上的 3.0 之前的版本以及 Windows 上的所有版本中,如果* block 为 true 且 timeout *为None,则此操作将在基础锁上进行不间断的 await。这意味着不会发生任何异常,尤其是 SIGINT 不会触发KeyboardInterrupt

  • Queue. get_nowait ( )
    • 等效于get(False)

提供两种方法来支持跟踪排队的任务是否已由守护程序使用者线程完全处理。

  • Queue. task_done ( )
    • 表示先前排队的任务已完成。由队列使用者线程使用。对于用于提取任务的每个get(),随后对task_done()的调用将告诉队列该任务的处理已完成。

如果join()当前正在阻止,它将在处理完所有项目后恢复(意味着收到put()进入队列的每个项目都收到task_done()调用)。

如果被调用的次数比队列中放置的项目多,则引发ValueError

  • Queue. join ( )
    • 阻塞直到队列中的所有项目都已获得并处理。

每当将项目添加到队列时,未完成任务的数量就会增加。每当使用者线程调用task_done()表示已检索到该项目并且该项目的所有工作已完成时,该计数就会减少。当未完成的任务计数降至零时,join()解除阻止。

如何 await 排队的任务完成的示例:

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 Objects

SimpleQueue对象提供了下面描述的公共方法。

  • SimpleQueue. qsize ( )

    • 返回队列的大概大小。注意,qsize()> 0 不能保证后续的 get()不会阻塞。
  • SimpleQueue. empty ( )

    • 如果队列为空,则返回True,否则返回False。如果 empty()返回False,则不能保证对 get()的后续调用不会阻塞。
  • SimpleQueue. put(* item block = True timeout = None *)

    • 将* item *放入队列。该方法永远不会阻塞并且总是会成功(除了潜在的低级错误,例如分配内存失败)。可选的 args * block timeout *被忽略,仅出于与Queue.put()的兼容性而提供。

CPython 实现细节: 此方法具有可重入的 C 实现。也就是说,一个put()get()调用可以被同一线程中的另一个put()调用break,而不会死锁或破坏队列内部的内部状态。这使其适合在析构函数(例如__del__方法或weakref回调)中使用。

  • SimpleQueue. put_nowait(* item *)

  • SimpleQueue. get(* block = True timeout = None *)

    • 从队列中删除并返回一个项目。如果可选参数 args * block 为 true 且 timeout None(默认值),则如有必要,请阻塞直到有可用项为止。如果 timeout 是一个正数,则它最多会阻塞 timeout 秒,如果在该时间内没有可用项,则会引发Empty异常。否则( block 为 false),如果有一个立即可用,则返回一个项目,否则引发Empty异常(在这种情况下, timeout *被忽略)。
  • SimpleQueue. get_nowait ( )

    • 等效于get(False)

See also

collections.deque是具有快速原子append()popleft()操作的无界队列的替代实现,这些操作不需要锁定并且还支持索引。