当我不处理它时如何打印异常?
How to print an exception when I'm not handling it?
我有以下代码:
# exc is a local variable of type Exception
# This is not inside an except block
if isinstance(exc, ClientError):
logging.debug("ClientError raised while loading %s:\n%s", package.id, traceback.format_exc())
continue
当此代码为 运行 且 exc
为 ClientError
类型时,format_exc()
仅打印出 NoneType: None
,因为当前未处理任何异常(代码不在 except
块内)。幸运的是 traceback
上似乎有 format_exception
方法,它与当前正在处理的异常无关,但为了调用它,我需要从中提取类型、值和 tb我的异常变量。我该怎么做?
exc
是如何产生的?如果它是从某个没有相应堆栈的函数 return 编辑的,那么无论如何都不可能生成正确的帧。最重要的是,没有 going deep into ctypes
就不可能生成 Traceback
对象,所以这可能不是我们想要的。
如果您所追求的实际上是记录异常的堆栈,那么使用 inspect.currentframe
and traceback.format_stack
可能会产生您所追求的结果。但是,如前所述,您需要获取尽可能接近错误发生位置的帧。考虑这个例子:
import traceback
import inspect
import logging
class Client:
pass
class ClientError(Exception):
pass
def get_client(name):
if name is None:
return ClientError('client must have a name')
return Client()
def connect(target, name=None):
exc = get_client(name)
if isinstance(exc, ClientError):
frames = inspect.currentframe()
logging.debug("ClientError raised while loading %s:\n%s",
target, ''.join(traceback.format_stack(frames)))
def main():
connect('somewhere')
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
main()
执行此操作将产生以下输出:
DEBUG:root:ClientError raised while loading somewhere:
File "foo.py", line 34, in <module>
main()
File "foo.py", line 30, in main
connect('somewhere')
File "foo.py", line 26, in connect
target, ''.join(traceback.format_stack(frames)))
请注意,堆栈恰好在调用完成的位置结束,因为 current_frame
的 return 值限制为 frames
。这就是为什么堆栈应该在它产生的地方生成和格式化,并退后一层。考虑这些更新的功能:
def get_client(name):
if name is None:
return (
ClientError('client must have a name'),
traceback.format_stack(inspect.currentframe().f_back),
)
return Client(), None
def connect(target, name=None):
exc, frames = get_client(name)
if isinstance(exc, ClientError):
stack = ''.join(frames)
logging.debug("ClientError raised while loading %s:\n%s",
target, stack)
执行
$ python foo.py
DEBUG:root:ClientError raised while loading somewhere:
File "foo.py", line 37, in <module>
main()
File "foo.py", line 33, in main
connect('somewhere')
File "foo.py", line 25, in connect
exc, frames = get_client(name)
注意跟踪是如何在产生异常的函数处结束的。
我有以下代码:
# exc is a local variable of type Exception
# This is not inside an except block
if isinstance(exc, ClientError):
logging.debug("ClientError raised while loading %s:\n%s", package.id, traceback.format_exc())
continue
当此代码为 运行 且 exc
为 ClientError
类型时,format_exc()
仅打印出 NoneType: None
,因为当前未处理任何异常(代码不在 except
块内)。幸运的是 traceback
上似乎有 format_exception
方法,它与当前正在处理的异常无关,但为了调用它,我需要从中提取类型、值和 tb我的异常变量。我该怎么做?
exc
是如何产生的?如果它是从某个没有相应堆栈的函数 return 编辑的,那么无论如何都不可能生成正确的帧。最重要的是,没有 going deep into ctypes
就不可能生成 Traceback
对象,所以这可能不是我们想要的。
如果您所追求的实际上是记录异常的堆栈,那么使用 inspect.currentframe
and traceback.format_stack
可能会产生您所追求的结果。但是,如前所述,您需要获取尽可能接近错误发生位置的帧。考虑这个例子:
import traceback
import inspect
import logging
class Client:
pass
class ClientError(Exception):
pass
def get_client(name):
if name is None:
return ClientError('client must have a name')
return Client()
def connect(target, name=None):
exc = get_client(name)
if isinstance(exc, ClientError):
frames = inspect.currentframe()
logging.debug("ClientError raised while loading %s:\n%s",
target, ''.join(traceback.format_stack(frames)))
def main():
connect('somewhere')
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
main()
执行此操作将产生以下输出:
DEBUG:root:ClientError raised while loading somewhere:
File "foo.py", line 34, in <module>
main()
File "foo.py", line 30, in main
connect('somewhere')
File "foo.py", line 26, in connect
target, ''.join(traceback.format_stack(frames)))
请注意,堆栈恰好在调用完成的位置结束,因为 current_frame
的 return 值限制为 frames
。这就是为什么堆栈应该在它产生的地方生成和格式化,并退后一层。考虑这些更新的功能:
def get_client(name):
if name is None:
return (
ClientError('client must have a name'),
traceback.format_stack(inspect.currentframe().f_back),
)
return Client(), None
def connect(target, name=None):
exc, frames = get_client(name)
if isinstance(exc, ClientError):
stack = ''.join(frames)
logging.debug("ClientError raised while loading %s:\n%s",
target, stack)
执行
$ python foo.py
DEBUG:root:ClientError raised while loading somewhere:
File "foo.py", line 37, in <module>
main()
File "foo.py", line 33, in main
connect('somewhere')
File "foo.py", line 25, in connect
exc, frames = get_client(name)
注意跟踪是如何在产生异常的函数处结束的。