Python:从 multiprocessing.Process 获取回溯
我试图从 multiprocessing.Process 获取回溯对象。 不幸的是,通过管道传递异常信息不起作用,因为无法对回溯对象进行腌制:
def foo(pipe_to_parent):
try:
raise Exception('xxx')
except:
pipe_to_parent.send(sys.exc_info())
to_child, to_self = multiprocessing.Pipe()
process = multiprocessing.Process(target = foo, args = (to_self,))
process.start()
exc_info = to_child.recv()
process.join()
print traceback.format_exception(*exc_info)
to_child.close()
to_self.close()
Traceback:
Traceback (most recent call last):
File "/usr/lib/python2.6/multiprocessing/process.py", line 231, in _bootstrap
self.run()
File "/usr/lib/python2.6/multiprocessing/process.py", line 88, in run
self._target(*self._args, **self._kwargs)
File "foo", line 7, in foo
to_parent.send(sys.exc_info())
PicklingError: Can't pickle <type 'traceback'>: attribute lookup __builtin__.traceback failed
是否有另一种方法来访问异常信息?我想避免传递格式化字符串。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
使用
tblib
您可以传递包装的异常并稍后重新引发它们: ,如果您在远程进程中捕获异常,请使用 ExceptionWrapper 包装它,然后将其传回。在主进程中调用
re_raise()
即可完成这项工作。Using
tblib
you can pass wrapped exceptions and reraise them later:So, if you catch an exception in your remote process, wrap it with
ExceptionWrapper
and then pass it back. Callingre_raise()
in the main process will do the work.由于
multiprocessing
确实会打印子进程中引发的异常的字符串内容,因此您可以将所有子进程代码包装在 try- except 中,以捕获任何异常,格式化相关堆栈跟踪,并引发新的 < code>Exception 在其字符串中保存所有相关信息:我与
multiprocessing.map
一起使用的函数示例:您得到的是一个堆栈跟踪,其中另一个格式化的堆栈跟踪作为错误消息,有助于调试。
Since
multiprocessing
does print the string contents of exceptions raised in child processes, you can wrap all your child process code in a try-except that catches any exceptions, formats the relavent stack traces, and raises a newException
that holds all the relevant information in its string:An example of a function I use with
multiprocessing.map
:What you get is a stack trace with another formatted stack trace as the error message, which helps with debugging.
使回溯对象变得可腌制似乎很困难。
但您只能发送
sys.exc_info()
的前 2 项,以及带有 traceback.extract_tb 方法:它为您提供:
(, Exception('xxx',), [('test_tb.py', 7, 'foo', "raise Exception('xxx')")])
然后,您将能够获取更多信息关于异常原因(文件名、引发异常的行号、方法名称和引发异常的语句)
It seems to be difficult to made picklable the traceback object.
But you can only send the 2 first items of
sys.exc_info()
, and a preformated traceback information with the traceback.extract_tb method :which give you :
(<type 'exceptions.Exception'>, Exception('xxx',), [('test_tb.py', 7, 'foo', "raise Exception('xxx')")])
And then, you'll be able to grab more informations about the exception cause (filename, line number where exception raised, method name and the statement that raise the exception)
Python 3
在 Python 3 中,现在
multiprocessing.pool.Async
的get
方法返回完整的回溯,请参阅 http://bugs.python.org/issue13831。Python 2
使用
traceback.format_exc
(这意味着格式化表达式)来获取回溯字符串。制作如下装饰器会更方便。
示例:
带有装饰器的回溯:
不带装饰器的回溯:
Python 3
In Python 3, now the
get
method ofmultiprocessing.pool.Async
returns full traceback, see http://bugs.python.org/issue13831.Python 2
Use the
traceback.format_exc
(which means formatted expetion) to get the traceback string.It would be much more covenient with making a decorator as below.
Example:
The traceback with the decorator:
The traceback without the decorator:
这是这个优秀答案的变体。两者都依赖 tblib 来存储回溯。
但是,
worker
函数不必返回异常对象(按照 OP 的要求),而是可以按原样保留,只需将其包装在try
/< code>except 来存储重新引发的异常。例子
This is a variation of this excellent answer. Both are relying on tblib for storing the traceback.
However, instead of having to return the exception object (as asked for by the OP), the
worker
function can be left as-is and is just wrapped intry
/except
to store exceptions for re-raise.Example
与 @Syrtis Major 和 @interfect 但是,使用 Python 3.6 进行测试:
用法:
The same solutions as @Syrtis Major and @interfect but, tested with Python 3.6:
Usage: