Custom exceptions are not raised properly when used in Multiprocessing Pool
我正在观察Python 3.3.4中我希望帮助理解的行为:为什么在正常执行函数时正确引发异常,而不是在函数池中执行函数时?
码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import multiprocessing class AllModuleExceptions(Exception): """Base class for library exceptions""" pass class ModuleException_1(AllModuleExceptions): def __init__(self, message1): super(ModuleException_1, self).__init__() self.e_string ="Message: {}".format(message1) return class ModuleException_2(AllModuleExceptions): def __init__(self, message2): super(ModuleException_2, self).__init__() self.e_string ="Message: {}".format(message2) return def func_that_raises_exception(arg1, arg2): result = arg1 + arg2 raise ModuleException_1("Something bad happened") def func(arg1, arg2): try: result = func_that_raises_exception(arg1, arg2) except ModuleException_1: raise ModuleException_2("We need to halt main") from None return result pool = multiprocessing.Pool(2) results = pool.starmap(func, [(1,2), (3,4)]) pool.close() pool.join() print(results) |
此代码产生此错误:
Exception in thread Thread-3:
Traceback (most recent call last):
File"/user/peteoss/encap/Python-3.4.2/lib/python3.4/threading.py", line 921, in _bootstrap_inner
self.run()
File"/user/peteoss/encap/Python-3.4.2/lib/python3.4/threading.py", line 869, in run
self._target(*self._args, **self._kwargs)
File"/user/peteoss/encap/Python-3.4.2/lib/python3.4/multiprocessing/pool.py", line 420, in _handle_results
task = get()
File"/user/peteoss/encap/Python-3.4.2/lib/python3.4/multiprocessing/connection.py", line 251, in recv
return ForkingPickler.loads(buf.getbuffer())
TypeError: __init__() missing 1 required positional argument: 'message2'
相反,如果我只是调用该函数,它似乎正确处理异常:
1 | print(func(1, 2)) |
生产:
Traceback (most recent call last):
File"exceptions.py", line 40, in
print(func(1, 2))
File"exceptions.py", line 30, in func
raise ModuleException_2("We need to halt main") from None
__main__.ModuleException_2
为什么
问题是您的异常类在其
这是Python异常的一个长期存在的问题,你可以在这个错误报告中阅读相当多的问题历史(其中一部分基本问题与酸洗异常是固定的,但不是你的部分'重击)。
总结一下这个问题:Python的base
该问题的解决方法是将自定义异常类在其
1 2 3 4 | class ModuleException_2(AllModuleExceptions): def __init__(self, message2): super(ModuleException_2, self).__init__(message2) # the change is here! self.e_string ="Message: {}".format(message2) |
另一个可能的解决方法是根本不调用超类
你的
我能够通过将签名更改为来解决问题
1 2 3 4 5 | class ModuleException_2(AllModuleExceptions): def __init__(self, message2=None): super(ModuleException_2, self).__init__() self.e_string ="Message: {}".format(message2) return |
但最好看看Pickling Class Instances以确保干净的实施。