Python “多处理”;OSError:[Errno 24]打开的文件太多";:如何清理工作和排队?

Python “多处理”;OSError:[Errno 24]打开的文件太多";:如何清理工作和排队?,python,multiprocessing,Python,Multiprocessing,当我使用完Queues以从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

当我使用完
Queue
s以从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()
因为这是一个操作错误,所以我的代码中没有导致问题的特定行。报告如下所示:

...
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__()
。。。
终止作业1006
开始工作1007
加入工作1007
终止作业1007
开始工作1008
加入工作1008
终止作业1008
开始工作1009
加入工作1009
终止作业1009
---------------------------------------------------------------------------
OSError回溯(最近一次调用上次)
在()
---->1断裂试验()
... 在breaktest()中
/队列中的usr/lib64/python2.6/multiprocessing/_init__.pyc(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__________(self、kind、value、maxvalue)
OSError:[Errno 24]打开的文件太多
>/usr/lib64/python2.6/multiprocessing/synchronize.py(49)\uuuu init\uuuu()

您的脚本在执行约1000个任务后会被卡住,因为这是单个进程的默认文件描述符限制

队列是通过保存文件描述符的管道实现的。通过GC正确删除管道。当您将它们存储在一个列表中时,它们不会被垃圾收集,文件描述符会泄漏,直到您的进程没有分配1024个描述符,然后崩溃


您是否需要将队列存储在列表中?

只需将问题语句代码中的
队列[ii].close()
替换为
队列[ii]=None
,即可避免显示错误 (感谢评论中的@Finch_Powers)

然而,我有更多的相关问题(这将是一个单独的问题),对于我真正的问题(这激发了我文章中的玩具示例),更一般的解决方案是小心避免任何循环变量直接引用队列或包含它们的任何对象。当我处理完队列时,再加上将list元素设置为None,可能再加上手动调用gc.collect(),这将导致在处理完每个队列时对每个队列进行适当的销毁(垃圾收集)。看

这有帮助的实际代码是中的runFunctionsInParallel函数

哪一行引发错误?我添加了一些信息,希望这些信息对判断哪一行引发错误有意义。您确定没有。。。打开的文件太多?您是否正在打开文件但忘记关闭它们?是否有“开始”/“加入”/“终止”的打印序列?在我的系统上,如果我将nTest设置为一个高值,它会在[None for ii in range(nTest)]上崩溃,并显示“MemoryError”。对不起。缺少关键上下文(现在已添加)。是的,我知道这些台词。在一台计算机上,每次完成1000个(大约!?)工作后,它都会死掉。在我的笔记本电脑上,它在505次(大约!?)的工作后死亡。除了代码中的“文件”之外,没有其他文件被打开。当前url:@CíceroAlves:谢谢!事实上,我已经将(Python 3版本的)repo移回了我原始URL中的位置,因此它是正确的,如cpblUtilities中所列。如果您展示一个解决此问题的最小示例,将更有帮助,gitlab示例做了很多工作,很难理解代码的哪一部分准确地解决了这个问题谢谢@P.V.:我编辑了答案,以便从显式解决方案开始。我还链接到一个更一般的问题。这非常有用,谢谢@CPBL