我正在Python 3.7中编写一个函数,该函数通过检查调用堆栈来处理多进程设置中的异常。
但是,我注意到,如果我将maxtasksperchild
对象指定为multiprocessing.Pool
选项,则某些进程(可能是第一个被杀死后创建的进程)将返回完全不同的堆栈调用函数甚至都不会跟踪。
再现的最小示例:
#!/usr/bin/env python3
import inspect
from multiprocessing import Pool
def mp_caller():
with Pool() as pool:
pool.map(_bork, range(10))
pool.close()
pool.join()
def mp_caller_kill():
with Pool(maxtasksperchild=1) as pool:
pool.map(_bork, range(10))
pool.close()
pool.join()
def _bork(i):
try:
if i % 3 == 0:
raise RuntimeError("BLAH")
print(i)
except:
handle_exception()
def handle_exception():
print("Stack info: {}".format(
[
f.function
for f in inspect.getouterframes(inspect.currentframe())
]
))
if __name__ == "__main__":
print("Without killing processes:")
mp_caller()
print("Killing processes:")
mp_caller_kill()
输出:
Without killing processes:
2
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller', '<module>']
4
5
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller', '<module>']
7
8
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller', '<module>']
1
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller', '<module>']
Killing processes:
2
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller_kill', '<module>']
1
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '__init__', 'Pool', 'mp_caller_kill', '<module>']
4
5
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '_maintain_pool', '_handle_workers', 'run', '_bootstrap_inner', '_bootstrap']
7
8
Stack info: ['handle_exception', '_bork', 'mapstar', 'worker', 'run', '_bootstrap', '_launch', '__init__', '_Popen', 'start', '_repopulate_pool', '_maintain_pool', '_handle_workers', 'run', '_bootstrap_inner', '_bootstrap']
请注意最后两个堆栈列表,它们在_maintain_pool
处发散,并且缺少我感兴趣的功能mp_caller_kill
。
是否有一种方法可以到达正确的堆栈,或者这些进程是否完全脱节?我需要使用maxtasksperchild
,因为依赖的C库没有释放内存。
谢谢。