详解Queue模块

Queue模块实现了多生产者,多消费者队列,对实现多个线程之间安全地交换信息非常有用。
该模块实现了三种类型的队列,它们的区别仅在于检索的顺序。在FIFO 队列中,添加的第一个任务是第一个检索的任务。在 LIFO队列中,最近添加的任务是第一个检索的(像堆栈一样)。使用优先级队列,任务将保持排序(使用heapq模块),并首先检索最低值任务。
在内部,这三种类型的队列使用锁来临时阻止竞争线程;但是它们并非旨在处理线程内的重入。此外,该模块实现了“简单” FIFO队列类型SimpleQueue。

详解Queue模块

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

classqueue.Queue(maxsize = 0)

FIFO队列的构造函数。maxsize是一个整数,用于设置可以放入队列的任务数的上限。达到此大小后,将无法继续放入,直到消耗队列项。如果 maxsize小于或等于零,则队列大小为无限大。

classqueue.LifoQueue(maxsize = 0)

LIFO队列的构造函数。maxsize是一个整数,用于设置可以放入队列的任务数的上限。达到此大小后,将无法继续放入,直到消耗队列项。如果 maxsize小于或等于零,则队列大小为无限大。

classqueue.PriorityQueue(maxsize = 0)

优先级队列的构造函数。maxsize是一个整数,用于设置可以放入队列的项目数的上限。达到此大小后,阻止放入,直到消耗队列项。如果 maxsize小于或等于零,则队列大小为无限大。
首先检索最低值的任务,任务的典型模式是以下形式的元组:(priority_number, data)
如果数据元素不具有可比性,则可以将数据包装在忽略数据项的类中,并仅比较优先级编号:

类queue.SimpleQueue

FIFO队列的构造函数。简单队列缺少任务跟踪等高级功能。(版本3.7中的新功能。)
异常queue.Empty
在对象为空时调用非阻塞get()(或 get_nowait())时引发异常Queue。
异常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)

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

Queue.put_nowait(item)

相当于put(item,False)

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

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

Queue.get_nowait()

相当于get(False)。

Queue.task_done()

表示以前排队的任务已完成,由队列使用者线程使用。对于用于获取任务的每个get(),对task_done()的调用将告诉队列任务的处理已完成。
如果 join()当前正在阻止,则它将在所有项目都已处理后恢复(意味着task_done()已收到已put()进入队列的每个项目的呼叫)。
如果被调用次数超过队列中放置的项目,将会抛出一个异常ValueError。

Queue.join()

阻止直到队列中的所有项目都已获取并处理完毕。每当项目添加到队列时,未完成任务的计数就会增加。每当消费者线程调用task_done()以指示该项目已被检索并且其上的所有工作都已完成时,计数就会下降。当未完成任务的数量降至零时,join()取消阻止。
如何等待排队任务完成的示例:

SimpleQueue对象

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

SimpleQueue.qsize()

返回队列的大小。注意,qsize()> 0不保证后续的get()不会阻塞。
SimpleQueue.empty()
如果队列为空返回True,否则返回False。如果empty()返回False,不保证对get()的后续调用不会阻塞。

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

将项目放入队列。该方法永远不会阻塞并始终成功(除了潜在的低级错误,例如无法分配内存)。可选的参数block和timeout 被忽略,仅提供兼容性Queue.put()。
CPython实现细节:此方法具有可重入的C实现。也就是说,一个put()或一个 get()调用可以被put()同一个线程中的另一个调用中断,而不会死锁或破坏队列中的内部状态,这使得它适用于__del__方法。

SimpleQueue.put_nowait(项目)

相当于put(item),提供兼容性 Queue.put_nowait()。

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

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

SimpleQueue.get_nowait()

相当于get(False)