[英]How to print an exception when I'm not handling it?
I have the following code: 我有以下代码:
# 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
When this code is run and exc
is of type ClientError
, format_exc()
just prints out NoneType: None
because no exception is currently being handled (the code is not inside an except
block). 当这个代码运行和
exc
是类型的ClientError
, format_exc()
仅仅打印出NoneType: None
因为没有异常被当前正在处理(代码不是内部的except
块)。 Luckily there appears to be the format_exception
method on traceback
that isn't coupled to whatever the current exception being handled is, but in order to call it I need to extract the type, values, and tb from my exception variable. 幸运的是,有似乎是
format_exception
的方法traceback
未连接到任何正在处理的当前异常,但为了调用它,我需要提取我的异常变量的类型,价值观和结核病。 How do I do this? 我该怎么做呢?
How is exc
being produced? exc
是如何产生的? If it is being returned from some function without the corresponding stack then it is not possible to produce the correct frames anyway. 如果它是从某个函数返回而没有相应的堆栈,则无论如何都无法生成正确的帧。 On top of that, it is not possible to generate a
Traceback
object without going deep into ctypes
, so this is likely not what is desired. 最重要的是,如果不深入
ctypes
,就不可能生成Traceback
对象,因此这可能不是所希望的。
If what you are after is actually the stack at where the exception was logged, making use of inspect.currentframe
and traceback.format_stack
may produce what you might be after. 如果您所追求的实际上是记录异常的堆栈,那么使用
inspect.currentframe
和traceback.format_stack
可能会产生您所追求的。 However, as mentioned, you will need to get the frames as close to where the error occurred. 但是,如前所述,您将需要使帧尽可能靠近发生错误的位置。 Consider this example:
考虑以下示例:
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()
Executing this will produce the following output: 执行此操作将产生以下输出:
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)))
Note that the stack ends exactly where the call is done, as the return value of the current_frame
is bounded to frames
. 请注意,由于
current_frame
的返回值限制为frames
,因此堆栈恰好在调用完成的地方结束。 This is why the stack should be generated and formatted at where it was produced, and step back one level. 这就是为什么应该在堆栈的生成位置对其进行格式化并使其后退一步的原因。 Consider these updated functions:
考虑以下更新的功能:
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)
Execution 执行
$ 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)
Note how the trace ends at the function that produced the exception. 注意跟踪如何在产生异常的函数处结束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.