通讯结束


问题内容

我正在学习使用“队列”模块,并且对如何使队列使用者线程知道队列已完成感到困惑。理想情况下,get()如果队列被标记为“完成”,我想在使用者线程中使用它并抛出异常。有没有比通过附加哨兵值标记队列中的最后一项更好的通信方式了?


问题答案:

原始(大多数已更改;请参见下面的更新)

基于Glenn Maynard和其他人的一些建议(谢谢!),我决定汇总实现该方法的后代。它以原始(未打包)模块的形式提供。我会再清理一点,并在我有更多时间时将其正确包装。目前,该模块仅包含类和异常类。我打算将其扩展为也包含和的子类。Queue.Queue``closeCloseableQueue``Closed``Queue.LifoQueue``Queue.PriorityQueue

目前,它处于一个相当初步的状态,也就是说,尽管它通过了测试套件,但实际上我还没有使用它。你的旅费可能会改变。我将通过令人振奋的消息来更新此答案。

CloseableQueue类不同于格伦的建议在关闭队列,以防将来有点putS,但并不妨碍未来gets,至队列被清空。这对我来说最有意义。清除队列的功能似乎可以作为单独的mixin
添加,而该mixin

与可关闭性功能正交。因此,基本上CloseableQueue,通过关闭队列,您可以指示最后一个元素已经存在put。还可以通过传递last=True给最终put调用来原子地执行此操作。后续调用put,和到后续调用get匹配那些描述一旦队列被清空,以及优秀的阻塞的呼叫,将提高Closed异常。

这在单个生产者为一个或多个消费者生成数据的情况下最有用,但对于消费者正在等待特定项目或一组项目的多重布局也很有用。特别是,它没有提供确定所有生产者都已完成生产的方法。要使该工作正常进行,就必须提供某种注册生产者的方法(.open()?),并表明生产者注册本身已经关闭。

非常欢迎提出建议和/或代码审查。我没有编写很多并发代码,但是希望测试套件足够彻底,以确保代码通过它的事实表明了代码的质量,而不是套件的缺乏。我能够重用Queue模块测试套件中的一堆代码:文件本身包含在此模块中,并用作各种子类和例程(包括回归测试)的基础。这可能(希望)有助于避免测试部门完全无能为力。代码本身只是覆盖Queue.getQueue.put进行了相当小的更改,并添加了closeclosed方法。

为了避免使代码与Queue模块本身一样向后兼容,我一直故意避免在代码本身和测试套件中使用上下文管理器等任何新奇的方法。我可能会在某个时候添加__enter____exit__方法。否则,contextlib的关闭函数应适用于CloseableQueue实例。

*:在这里我宽松地使用术语“ mixin”。由于Queue模块的类是老式的,因此需要使用类工厂函数来混合mixin。适用一些限制;在Guido禁止的地方提供空白。

更新

现在,CloseableQueue模块提供CloseableLifoQueueCloseablePriorityQueue类。我还添加了一些便利功能来支持迭代。仍然需要将其作为适当的软件包进行返工。有一个类工厂函数,可以方便地对其他Queue.Queue派生类进行子类化。

更新2

CloseableQueue现在可以通过PyPI使用,例如

$ easy_install CloseableQueue

欢迎发表评论和批评,特别是来自此答案的匿名评论家。