在使用多处理模块的Python中,有两种队列:
他们之间有什么区别?
from multiprocessing import Queue
q = Queue()
q.put(item) # Put an item on the queue
item = q.get() # Get an item from the queue
from multiprocessing import JoinableQueue
q = JoinableQueue()
q.task_done() # Signal task completion
q.join() # Wait for completion
答案 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。