我一直在努力寻找为什么Pool
工人中引发的异常没有传播的原因,即它正在默默地继续进行。我在代码中添加了很多异常,以识别最终可能在何处捕获并发现了奇怪的行为。
我有一个课程,例如:
class Pipeline:
def __call__(self, **kwargs):
raise ValueError()
for module in self.modules:
print("Pipeline: call module: %s" % str(module))
# raise BaseException()
raise ValueError()
o = module(**kwargs)
kwargs.update(o)
return o, kwargs
在Pool
中调用了哪些实例(实际上是pathos.ProcessingPool
而不是multiprocessing.Pool
,不确定在这种情况下它可能会发生什么变化),即
from pathos.multiprocessing import ProcessingPool as Pool
with Pool(processes=n_thread) as pool:
pool.map(run_exp_args, [...])
def run_exp_args([...]):
[...]
p = Pipeline(...)
o, k = p(**kwargs)
如您所料,这会在进入循环之前引发ValueError
,在Pipeline.__call__
(由跟踪的行号确认)中,它将停止程序并显示相关的跟踪。
奇怪的是,如果我首先对此ValueError
进行评论(但将其保留在循环中),则此异常不会传播,只会被忽略。
现在,如果我通过取消注释右上方的行来引发BaseException
,则会引发此异常,我会看到跟踪,但不会停止整个程序。
我一直在尝试n_thread=1
,以确保我的输出相关。
print
之前的raise
有所不同...(删除它最终解决了问题)
如果我删除循环中的打印件,则会显示ValueError
,并停止程序。
所以基本上:
class Pipeline:
def __init__(self, *args):
self.modules = [*args]
def __call__(self, **kwargs):
for module in self.modules:
print()
raise ValueError()
o = module(**kwargs)
kwargs.update(o)
return o, kwargs
运行时没有错误
class Pipeline:
def __init__(self, *args):
self.modules = [*args]
def __call__(self, **kwargs):
for module in self.modules:
raise ValueError()
o = module(**kwargs)
kwargs.update(o)
return o, kwargs
失败(这就是我想要的!)。
实际上,真正的逻辑发生在o = module(...)
调用中,该调用包含很多指令,包括print
和未引发的异常。
这是一个非常烦人的问题,因为我不能在并行模式下信任我的程序,因此我必须在没有Pool的情况下运行它(特别是因为有重要的assert
被忽略了)。
您有什么想法吗?
注释:
(1)提出BaseException
的想法来自Exception thrown in multiprocessing Pool not detected,但是线程并没有真正解决一个真正的问题:为什么两个ValueError
的行为不同?
使用:https://gist.github.com/oseiskar/dbd38098038df8944e21b41c42668440似乎可以解决我的问题。