当我使用它们时,我会尽力关闭并清理Queue
,以便从Python的多处理模块中收集进程的输出。这里有一些代码因某些原因而死亡,因为太多的打开文件"。我还能做些什么来清理完整的工作/队列,以便我可以尽可能多地完成工作?
# The following [fails to] demonstrates how to clean up jobs and queues (the queues is key?) to avoid the OSError of too many files open.
def dummy(inv,que):
que.put(inv)
return(0)
from multiprocessing import Process, Queue, cpu_count
nTest=2800
queues=[None for ii in range(nTest)]
for ii in range(nTest):
queues[ii]=Queue()
job=Process(target=dummy, args=[ii,queues[ii]])
job.start()
print('Started job %d'%ii)
job.join()
print('Joined job %d'%ii)
job.terminate()
print('Terminated job %d'%ii)
queues[ii].close()
因为它是一个OSError,我的代码中没有特定的行导致问题。报告看起来像这样:
...
Terminated job 1006
Started job 1007
Joined job 1007
Terminated job 1007
Started job 1008
Joined job 1008
Terminated job 1008
Started job 1009
Joined job 1009
Terminated job 1009
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-2-5f057cd2fe88> in <module>()
----> 1 breaktest()
... in breaktest()
/usr/lib64/python2.6/multiprocessing/__init__.pyc in Queue(maxsize)
/usr/lib64/python2.6/multiprocessing/queues.pyc in __init__(self, maxsize)
/usr/lib64/python2.6/multiprocessing/synchronize.pyc in __init__(self)
/usr/lib64/python2.6/multiprocessing/synchronize.pyc in __init__(self, kind, value, maxvalue)
OSError: [Errno 24] Too many open files
> /usr/lib64/python2.6/multiprocessing/synchronize.py(49)__init__()
答案 0 :(得分:1)
您的脚本在~1000个任务后卡住了,因为这是单个进程的文件描述符的默认限制。
使用包含文件描述符的Pipes实现队列。通过GC正确删除管道。当您将它们存储在列表中时,它们不会收集垃圾并且文件描述符会泄漏,直到您的进程没有分配1024个然后它就会崩溃。
您是否需要将队列存储在列表中?
答案 1 :(得分:1)
我真实问题的更一般的解决方案(在我的帖子中激发了玩具示例)是要小心避免任何循环变量直接引用队列或包含它们的任何对象。结合在我完成队列时将列表元素设置为None,可能与手动调用gc.collect()相结合,导致每个队列在完成每个队列时进行适当的破坏(垃圾收集)。
@Finch_Powers在发表评论时解决了这个问题。
我怀疑不同系统的体验可能会有所不同。
这有助于实际的代码是runFunctionsInParallel函数 https://gitlab.com/cpbl/cpblUtilities/blob/master/parallel.py