8.10. 队列-同步队列类

Note

Queue模块在 Python 3 中已重命名为queue2to3工具在将源转换为 Python 3 时将自动适应导入。

源代码: Lib/Queue.py


Queue模块实现多生产者,多 Consumer 队列。当必须在多个线程之间安全地交换信息时,它在线程编程中特别有用。此模块中的Queue类实现所有必需的锁定语义。这取决于 Python 中线程支持的可用性。参见threading模块。

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

Queue模块定义以下类和异常:

    • class * Queue. Queue(* maxsize = 0 *)
    • FIFO 队列的构造函数。 * maxsize 是一个整数,用于设置可以放入队列中的项目数的上限。一旦达到此大小,插入将被阻塞,直到消耗队列项目为止。如果 maxsize *小于或等于零,则队列大小为无限。
    • class * Queue. LifoQueue(* maxsize = 0 *)
    • LIFO 队列的构造函数。 * maxsize 是一个整数,用于设置可以放入队列中的项目数的上限。一旦达到此大小,插入将被阻塞,直到消耗队列项目为止。如果 maxsize *小于或等于零,则队列大小为无限。

2.6 版的新Function。

    • class * Queue. PriorityQueue(* maxsize = 0 *)
    • 优先级队列的构造函数。 * maxsize 是一个整数,用于设置可以放入队列中的项目数的上限。一旦达到此大小,插入将被阻塞,直到消耗队列项目为止。如果 maxsize *小于或等于零,则队列大小为无限。

最低值的条目首先被检索(最低值的条目是sorted(list(entries))[0]返回的条目)。条目的典型模式是(priority_number, data)形式的 Tuples。

2.6 版的新Function。

See also

collections.deque是具有不需要锁定的快速原子append()popleft()操作的无界队列的替代实现。

8.10.1. 队列对象

队列对象(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 * [,* timeout *]])

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

2.3 版中的新Function:* timeout *参数。

  • Queue. put_nowait(* item *)

    • 等效于put(item, False)
  • Queue. get([* block * [,* timeout *]])

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

2.3 版中的新Function:* timeout *参数。

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

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

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

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

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

2.5 版的新Function。

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

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

2.5 版的新Function。

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

def worker():
    while True:
        item = q.get()
        do_work(item)
        q.task_done()

q = Queue()
for i in range(num_worker_threads):
     t = Thread(target=worker)
     t.daemon = True
     t.start()

for item in source():
    q.put(item)

q.join()       # block until all tasks are done