我想在不退出的情况下捕获和记录异常,例如,
try:
do_stuff()
except Exception as err:
print(Exception, err)
# I want to print the entire traceback here,
# not just the exception name and details
我想打印与抛出异常时打印的完全相同的输出,而不使用try/,只是拦截异常,并且我不希望它退出程序。
我想在不退出的情况下捕获和记录异常,例如,
try:
do_stuff()
except Exception as err:
print(Exception, err)
# I want to print the entire traceback here,
# not just the exception name and details
我想打印与抛出异常时打印的完全相同的输出,而不使用try/,只是拦截异常,并且我不希望它退出程序。
当前回答
在python3(适用于3.9)中,我们可以定义一个函数,并可以在任何需要打印详细信息的地方使用它。
import traceback
def get_traceback(e):
lines = traceback.format_exception(type(e), e, e.__traceback__)
return ''.join(lines)
try:
1/0
except Exception as e:
print('------Start--------')
print(get_traceback(e))
print('------End--------')
try:
spam(1,2)
except Exception as e:
print('------Start--------')
print(get_traceback(e))
print('------End--------')
输出如下所示:
bash-3.2$ python3 /Users/soumyabratakole/PycharmProjects/pythonProject/main.py
------Start--------
Traceback (most recent call last):
File "/Users/soumyabratakole/PycharmProjects/pythonProject/main.py", line 26, in <module>
1/0
ZeroDivisionError: division by zero
------End--------
------Start--------
Traceback (most recent call last):
File "/Users/soumyabratakole/PycharmProjects/pythonProject/main.py", line 33, in <module>
spam(1,2)
NameError: name 'spam' is not defined
------End--------
其他回答
Python 3解决方案
stacktrace_helper.py:
from linecache import getline
import sys
import traceback
def get_stack_trace():
exc_type, exc_value, exc_tb = sys.exc_info()
trace = traceback.format_stack()
trace = list(filter(lambda x: ("\\lib\\" not in x and "/lib/" not in x and "stacktrace_helper.py" not in x), trace))
ex_type = exc_type.__name__
ex_line = exc_tb.tb_lineno
ex_file = exc_tb.tb_frame.f_code.co_filename
ex_message = str(exc_value)
line_code = ""
try:
line_code = getline(ex_file, ex_line).strip()
except:
pass
trace.insert(
0, f'File "{ex_file}", line {ex_line}, line_code: {line_code} , ex: {ex_type} {ex_message}',
)
return trace
def get_stack_trace_str(msg: str = ""):
trace = list(get_stack_trace())
trace_str = "\n".join(list(map(str, trace)))
trace_str = msg + "\n" + trace_str
return trace_str
Traceback.format_exc()或sys.exc_info()将产生更多信息,如果这是你想要的。
import traceback
import sys
try:
do_stuff()
except Exception:
print(traceback.format_exc())
# or
print(sys.exc_info()[2])
如果你正在调试,只想查看当前的堆栈跟踪,你可以简单地调用:
traceback.print_stack ()
没有必要为了再次捕获异常而手动引发异常。
你可以这样做:
try:
do_stuff()
except Exception, err:
print(Exception, err)
raise err
如何在不停止程序的情况下打印完整的回溯?
当你不想因为一个错误而停止你的程序时,你需要用try/except来处理这个错误:
try:
do_something_that_might_error()
except Exception as error:
handle_the_error(error)
要提取完整的回溯,我们将使用标准库中的traceback模块:
import traceback
并创建一个相当复杂的stacktrace来演示我们得到完整的stacktrace:
def raise_error():
raise RuntimeError('something bad happened!')
def do_something_that_might_error():
raise_error()
印刷
要打印完整的回溯,请使用traceback。print_exc方法:
try:
do_something_that_might_error()
except Exception as error:
traceback.print_exc()
打印:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
优于打印、日志:
但是,最佳实践是为您的模块设置一个记录器。它将知道模块的名称,并且能够更改级别(在其他属性中,例如处理程序)
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
在这种情况下,您将需要记录器。异常函数改为:
try:
do_something_that_might_error()
except Exception as error:
logger.exception(error)
日志:
ERROR:__main__:something bad happened!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
或者,您可能只想要字符串,在这种情况下,您将需要回溯。Format_exc函数改为:
try:
do_something_that_might_error()
except Exception as error:
logger.debug(traceback.format_exc())
日志:
DEBUG:__main__:Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
结论
对于这三个选项,我们看到我们得到的输出和我们有错误时是一样的:
>>> do_something_that_might_error()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
使用哪种
性能问题在这里并不重要,因为IO通常占主导地位。我更喜欢,因为它精确地以向前兼容的方式执行请求:
logger.exception(error)
日志级别和输出可以调整,这样就可以很容易地关闭,而不需要修改代码。通常做直接需要的是最有效的方法。