我正在尝试使用多处理编写 Python 2.6 (OSX) 程序,并且我想用超过默认的 32767 项来填充队列。
from multiprocessing import Queue
Queue(2**15) # raises OSError
Queue(32767)
工作正常,但任何更高的数字(例如Queue(32768)
)失败OSError: [Errno 22] Invalid argument
这个问题有解决方法吗?
我正在尝试使用多处理编写 Python 2.6 (OSX) 程序,并且我想用超过默认的 32767 项来填充队列。
from multiprocessing import Queue
Queue(2**15) # raises OSError
Queue(32767)
工作正常,但任何更高的数字(例如Queue(32768)
)失败OSError: [Errno 22] Invalid argument
这个问题有解决方法吗?
一种方法是multiprocessing.Queue
用一个自定义类包装你(只是在生产者方面,或者从消费者的角度透明地)。使用它,您可以将要分派到Queue
要包装的对象的项目排队,并且仅在空间可用时将本地队列(Pythonlist()
对象)中的内容提供给空间,并在空间已满multiprocess.Queue
时进行异常处理以进行节流。Queue
这可能是最简单的方法,因为它应该对其余代码的影响最小。自定义类的行为应该像队列一样,同时隐藏multiprocessing.Queue
抽象背后的底层。
(一种方法可能是让您的生产者使用线程,一个线程来管理从线程Queue
到您的调度multiprocessing.Queue
以及实际上只是提供线程的任何其他线程Queue
)。
我已经回答了最初的问题,但我确实想补充一点,Redis列表非常可靠,Python 模块对它们的支持非常容易用于实现类似队列的对象。这些具有允许一个人在多个节点(跨网络)以及多个进程上横向扩展的优势。
基本上要使用那些,您只需为队列名称选择一个键(字符串),让您的生产者推入其中,并让您的工作人员(任务消费者)循环阻止来自该键的弹出。
Redis BLPOP 和 BRPOP 命令都采用一个键列表(列表/队列)和一个可选的超时值。他们返回一个元组(键,值)或无(超时)。因此,您可以轻松编写一个事件驱动系统,该系统与熟悉的select()结构非常相似(但级别更高)。您唯一需要注意的是缺少键和无效的键类型(当然,只需使用异常处理程序包装您的队列操作)。(如果某些其他应用程序在您的共享 Redis 服务器上停止,删除键或用字符串/整数或其他类型的值替换您用作队列的键......那么,此时您会遇到不同的问题)。:)
该模型的另一个优点是 Redis 确实将其数据持久化到磁盘。因此,如果您选择允许,您的工作队列可以在系统重新启动后继续存在。
(当然,如果您真的想在 SQLlite 或任何其他 SQL 系统中实现一个简单的 Queue 作为表;只需使用某种自动递增索引进行排序,并使用一列来标记每个项目已经“完成”(已使用);但这确实比使用 Redis 提供的“开箱即用”更复杂)。
在 MacOSX 上为我工作
>>> import Queue
>>> Queue.Queue(30000000)
<Queue.Queue instance at 0x1006035f0>