我在Linux上使用Python 2.7.8,并且在使用multiprocessing.Pool()的程序中看到一致的失败。当我将maxtasksperchild设置为None时,一切都很好,当测试各种过程值时。但是如果我设置maxtasksperchild = n(n> = 1),那么我总是以未捕获的异常结束。这是主要块:
if __name__ == "__main__":
options = parse_cmdline()
subproc = Sub_process(options)
lock = multiprocessing.Lock()
[...]
pool = multiprocessing.Pool(processes=options.processes,
maxtasksperchild=options.maxtasksperchild)
imap_it = pool.imap(recluster_block, subproc.input_block_generator())
#import pdb; pdb.set_trace()
for count, result in enumerate(imap_it):
print "Count = {}".format(count)
if result is None or len(result) == 0:
# presumably error was reported
continue
(interval, block_id, num_hpcs, num_final, retlist) = result
for c in retlist:
subproc.output_cluster(c, lock)
print "About to close_outfile."
subproc.close_outfile()
print "About to close pool."
pool.close()
print "About to join pool."
pool.join()
为了进行调试,我添加了一个print语句,显示循环的次数。这是几个运行:
$ $prog --processes=2 --maxtasksperchild=2
Count = 0
Count = 1
Count = 2
Traceback (most recent call last):
File "[...]reclustering.py", line 821, in <module>
for count, result in enumerate(imap_it):
File "[...]/lib/python2.7/multiprocessing/pool.py", line 659, in next
raise value
TypeError: 'int' object is not callable
$ $prog --processes=2 --maxtasksperchild=1
Count = 0
Count = 1
Traceback (most recent call last):
[same message as above]
如果我没有设置maxtasksperchild,程序将成功运行完成。此外,如果我取消注释“import pdb; pdb.set_trace()”行并输入调试器,则不会出现问题(Heisenbug)。那么,我在这里的代码中做错了吗?是否有生成输入的代码(subproc.input_block_generator)或处理它的代码(recluster_block)的条件,已知会导致这样的问题?谢谢!
答案 0 :(得分:1)
maxtasksperchild导致多处理重新生成子进程。我们的想法是摆脱任何正在建立的残余。问题是,你可以从父母那里得到新的东西。当孩子重生时,它获得父进程的当前状态,这与orignal spawn不同。您正在脚本的全局命名空间中进行工作,因此您正在改变孩子将会看到的环境。具体来说,您使用一个名为&#39; count&#39;的变量。这掩盖了以前从itertools导入计数&#39;言。
解决此问题:
使用命名空间(itertools.count,就像你在评论中所说的那样)来减少名称冲突
在函数中完成工作,以便局部变量不会传播给孩子。