我是否需要在多处理异常时手动调用 pool.terminate?
Do I need to call pool.terminate manually upon excepton in multiprocessing?
似乎以下 2 个片段具有相同的行为:
def sqr(a):
time.sleep(1.2)
print 'local {}'.format(os.getpid())
if a == 20:
raise Exception('fff')
return a * a
pool = Pool(processes=4)
甲:
try:
r = [pool.apply_async(sqr, (x,)) for x in range(100)]
pool.close()
for item in r:
item.get(timeout=999999)
except:
pool.terminate()
raise
finally:
pool.join()
print 'main {}'.format(os.getpid())
乙:
r = [pool.apply_async(sqr, (x,)) for x in range(100)]
pool.close()
for item in r:
item.get(timeout=999999)
pool.join()
最初我认为如果我不这样做 terminate
,即使主进程退出,所有其他进程也会在后台 运行。但是我检查了 htop
并且似乎所有子进程都在异常被触发后立即退出。
当您调用 pool.close()
时,您是在告诉 Pool
不再向其发送任务。这允许它在当前任务队列处理完毕后立即关闭其工作进程——不需要显式 terminate()
调用。这在文档中提到:
close()
Prevents any more tasks from being submitted to the pool. Once all the tasks have been completed the worker processes will exit.
请注意,任务是成功完成还是抛出异常并不重要;无论哪种方式,任务都完成了。
此外,Pool
中的所有工作进程都以 daemon=True
启动,这意味着它们将在父进程准备好退出时立即终止。在您的情况下,您正在对正在处理的每个项目调用 get()
,这将导致在父项中重新引发子项中抛出的异常。发生这种情况时,父进程退出,这会自动终止所有工作进程。
似乎以下 2 个片段具有相同的行为:
def sqr(a):
time.sleep(1.2)
print 'local {}'.format(os.getpid())
if a == 20:
raise Exception('fff')
return a * a
pool = Pool(processes=4)
甲:
try:
r = [pool.apply_async(sqr, (x,)) for x in range(100)]
pool.close()
for item in r:
item.get(timeout=999999)
except:
pool.terminate()
raise
finally:
pool.join()
print 'main {}'.format(os.getpid())
乙:
r = [pool.apply_async(sqr, (x,)) for x in range(100)]
pool.close()
for item in r:
item.get(timeout=999999)
pool.join()
最初我认为如果我不这样做 terminate
,即使主进程退出,所有其他进程也会在后台 运行。但是我检查了 htop
并且似乎所有子进程都在异常被触发后立即退出。
当您调用 pool.close()
时,您是在告诉 Pool
不再向其发送任务。这允许它在当前任务队列处理完毕后立即关闭其工作进程——不需要显式 terminate()
调用。这在文档中提到:
close()
Prevents any more tasks from being submitted to the pool. Once all the tasks have been completed the worker processes will exit.
请注意,任务是成功完成还是抛出异常并不重要;无论哪种方式,任务都完成了。
此外,Pool
中的所有工作进程都以 daemon=True
启动,这意味着它们将在父进程准备好退出时立即终止。在您的情况下,您正在对正在处理的每个项目调用 get()
,这将导致在父项中重新引发子项中抛出的异常。发生这种情况时,父进程退出,这会自动终止所有工作进程。