队列与Python中的JoinableQueue

时间:2015-07-05 12:16:54

标签: python queue multiprocessing

在使用多处理模块的Python中,有两种队列:

  • 队列
  • JoinableQueue。

他们之间有什么区别?

队列

from multiprocessing import Queue
q = Queue()
q.put(item) # Put an item on the queue
item = q.get() # Get an item from the queue

JoinableQueue

from multiprocessing import JoinableQueue
q = JoinableQueue()
q.task_done() # Signal task completion
q.join() # Wait for completion

2 个答案:

答案 0 :(得分:18)

JoinableQueue有方法join()task_done()Queue没有方法。

  

类multiprocessing.Queue([maxsize])

     

返回使用管道和一些锁/信号量实现的进程共享队列。当进程首先将项目放入队列时,将启动一个进给器线程,该线程将对象从缓冲区传输到管道中。

     

标准库的Queue模块中常见的Queue.Empty和Queue.Full异常被引发以指示超时。

     

Queue实现了Queue.Queue的所有方法,但task_done()和join()除外。

  

类multiprocessing.JoinableQueue([maxsize])

     

JoinableQueue是一个Queue子类,是一个另外有task_done()和join()方法的队列。

     

<强> task_done()

     

表示以前排队的任务已完成。由队列使用者线程使用。对于用于获取任务的每个get(),对task_done()的后续调用会告诉队列该任务的处理已完成。

     

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

     

如果调用的次数超过队列中放置的项目,则引发ValueError。

     

<强>加入()

     

阻止,直到队列中的所有项目都已获得并处理完毕。

     

每当项目添加到队列时,未完成任务的数量就会增加。每当消费者线程调用task_done()以指示该项目已被检索并且其上的所有工作都已完成时,计数就会下降。当未完成任务的数量降至零时,join()取消阻塞。

如果您使用JoinableQueue,则必须为从队列中删除的每个任务调用JoinableQueue.task_done(),否则用于计算未完成任务数量的信号量最终可能会溢出,从而引发异常。

答案 1 :(得分:0)

根据文档,很难确定radix ** exponent - 1实际上是空的。使用 def cycle_walking (x, encipher) { if encipher(x) is an element of M return encipher(x) else return cycle_walking(encipher(x)) } ,您可以通过调用Queue等待队列清空。如果您要分批完成工作,并且在每批结束时都要做一些离散的操作,这可能会有所帮助。

例如,也许您一次通过队列处理1000个项目,然后向用户发送已完成另一批处理的推送通知。使用普通的JoinableQueue来实现这一点非常困难。

它可能类似于:

q.join()

注意:我实际上没有运行此代码。如果将项目拖出队列的速度比放入项目的速度快,则可能会提早完成。在这种情况下,此代码至少每1000个项目发送一次更新,而且更新频率可能更高。对于进度更新,可能没问题。如果重要的是精确到1000,则可以使用Queue并在import multiprocessing as mp BATCH_SIZE = 1000 STOP_VALUE = 'STOP' def consume(q): for item in iter(q.get, STOP_VALUE): try: process(item) # Be very defensive about errors since they can corrupt pipes. except Exception as e: logger.error(e) finally: q.task_done() q = mp.JoinableQueue() with mp.Pool() as pool: # Pull items off queue as fast as we can whenever they're ready. for _ in range(mp.cpu_count()): pool.apply_async(consume, q) for i in range(0, len(URLS), BATCH_SIZE): # Put `BATCH_SIZE` items in queue asynchronously. pool.map_async(expensive_func, URLS[i:i+BATCH_SIZE], callback=q.put) # Wait for the queue to empty. q.join() notify_users() # Stop the consumers so we can exit cleanly. for _ in range(mp.cpu_count()): q.put(STOP_VALUE) 发布时检查它是否为1000。