我正在尝试捕获子进程引发的异常,并且遇到了一些问题。我的代码的要点是:
class CustomException(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg
def update(partition):
if os.getpid() % 2 == 0:
raise CustomException('PID was divisible by 2!')
else:
# Do something fancy
if __name__ == '__main__':
try:
some_response = get_response_from_another_method()
partition_size = 100
p = Pool(config.NUMBER_OF_PROCESSES)
for i in range(0, NUMBER_OF_PROCESSES):
partition = get_partition(some_response, partition_size)
x = p.apply_async(update, args=(partition,))
x.get()
p.close()
p.join()
except CustomException as e:
log.error('There was an error')
if email_notifier.send_notification(e.msg):
log.debug('Email notification sent')
else:
log.error('An error occurred while sending an email.')
当我跑步时,我看到了:
File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py", line 532, in __bootstrap_inner
self.run()
File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py", line 484, in run
self.__target(*self.__args, **self.__kwargs)
File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/multiprocessing/pool.py", line 259, in _handle_results
task = get()
TypeError: ('__init__() takes exactly 2 arguments (1 given)', <class 'CustomException'>, ())
是否有一些设施可以做到这一点?谢谢!
答案 0 :(得分:1)
简而言之,这在Python 2中是一个怪癖,在bug report中引用了一个相关的问题。它与如何腌制异常有关。最简单的解决方案可能是改变CustomException
,以便调用其父类初始值设定项。或者,如果你能够,我建议你转向Python 3。
例如,此代码在Python 2和Python 3中均可正常工作:
from multiprocessing import Pool
class CustomException(Exception):
pass
def foo():
raise CustomException('PID was divisible by 2!')
pool = Pool()
result = pool.apply_async(foo, [])
但是如果我们改变CustomException
以便它有一个必需的参数:
class CustomException(Exception):
def __init__(self, required):
self.required = required
上面的示例导致在Python 2下引发TypeError
。它在Python 3下工作。
问题是CustomException
继承了Exception
的{{1}}方法,该方法告诉Python如何挑选实例。继承的__reduce__
对__reduce__
的呼叫签名一无所知,因此无法正确进行解链。
快速解决方法是简单地调用父类的CustomException
:
__init__
但是因为你真的没有对这个消息做任何特别的事情,为什么不定义:
class CustomException(Exception):
def __init__(self, msg):
super(Exception, self).__init__()
self.msg = msg