探索新方法:展示 Python 异常信息的方式与众不同
来源:51CTO.COM
时间:2024-01-22 23:15:02 333浏览 收藏
在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是文章学习者,那么本文《探索新方法:展示 Python 异常信息的方式与众不同》就很适合你!本篇内容主要包括##content_title##,希望对大家的知识积累有所帮助,助力实战开发!

简介
在日常开发中,我们的大部分时间都会花在阅读traceback模块信息以及调试代码上。本文我们将改进traceback模块,让其中的提示信息更加简洁准确。
基于这一目的,我们将会自定义Exception Hooks(异常处理钩子),用来去除traceback中的冗余信息,只留下解决报错所需的内容。此外,我还会介绍一些好用的第三方库,你可以直接使用其中的Exception Hooks,来简化traceback模块。
Exception Hooks
假如程序的异常信息没有被try/catch捕获到,python解释器就会调用sys.excepthook()函数,它会接收3个参数,分别是:type, value, traceback。这个函数也被称为Exception Hook,会输出程序的异常信息。
我们来看看下面这个例子:
import sys
def exception_hook(exc_type, exc_value, tb):
print('Traceback:')
filename = tb.tb_frame.f_code.co_filename
name = tb.tb_frame.f_code.co_name
line_no = tb.tb_lineno
print(f"File {filename} line {line_no}, in {name}")
# Exception type 和 value
print(f"{exc_type.__name__}, Message: {exc_value}")
sys.excepthook = exception_hook在这个例子中,我们可以从traceback (tb)对象中获取到异常信息出现的位置,位置信息包括:文件名(f_code.co_filename),函数/模块名(f_code.co_name), 和行数(tb_lineno)。此外,我们可以使用exc_type和exc_value变量来获取异常信息的内容。
当我们调用一个会产生错误的函数时,exception_hook会输出如下内容:
def do_stuff():
# 写一段会产生异常的代码
raise ValueError("Some error message")
do_stuff()
# Traceback:
# File /home/some/path/exception_hooks.py line 22, in <module>
# ValueError, Message: Some error message</module>上述例子提供了一部分异常信息,但要想获取调试代码所需的全部信息,并知道异常出现的时间及位置,我们还需要深入研究下traceback对象:
def exception_hook(exc_type, exc_value, tb):
local_vars = {}
while tb:
filename = tb.tb_frame.f_code.co_filename
name = tb.tb_frame.f_code.co_name
line_no = tb.tb_lineno
print(f"File {filename} line {line_no}, in {name}")
local_vars = tb.tb_frame.f_locals
tb = tb.tb_next
print(f"Local variables in top frame: {local_vars}")
...
# File /home/some/path/exception_hooks.py line 41, in <module>
# File /home/some/path/exception_hooks.py line 7, in do_stuff
# Local variables in top frame: {'some_var': 'data'}</module>由上面的例子可以看出,traceback对象(tb)本质上是一个链表 - 存储着所有出现的exceptions。因此可以使用tb_next对tb进行遍历,并打印每一个异常的信息。在此基础上,还可以使用tb_frame.f_locals属性将变量输出到console中,这有助于调试代码。
使用traceback对象输出异常信息是可行的,但是比较麻烦,此外输出的信息可读性较差。更方便的做法是使用traceback模块,该模块内置了许多提取异常信息的辅助函数。
目前我们已经介绍了Exception Hooks的基础知识,接下来我们可以自定义一个exception hooks,并加入一些实用的特性。
自定义Exception Hooks
- 我们还可以让异常信息自动存入文件中,在之后调试代码的时候查看:
LOG_FILE_PATH = "./some.log"
FILE = open(LOG_FILE_PATH, mode="w")
def exception_hook(exc_type, exc_value, tb):
FILE.write("*** Exception: ***n")
traceback.print_exc(file=FILE)
FILE.write("n*** Traceback: ***n")
traceback.print_tb(tb, file=FILE)
# *** Exception: ***
# NoneType: None
#
# *** Traceback: ***
# File "/home/some/path/exception_hooks.py", line 82, in <module>
# do_stuff()
# File "/home/some/path/exception_hooks.py", line 7, in do_stuff
# raise ValueError("Some error message")</module>- 异常信息默认会存储到stderr中,如果你想改变存储位置,可以这样做:
import logging
logging.basicConfig(
level=logging.CRITICAL,
format='[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
datefmt='%H:%M:%S',
stream=sys.stdout
)
def exception_hook(exc_type, exc_value, exc_traceback):
logging.critical("Uncaught exception:", exc_info=(exc_type, exc_value, exc_traceback))
# [17:28:33] {/home/some/path/exception_hooks.py:117} CRITICAL - Uncaught exception:
# Traceback (most recent call last):
# File "/home/some/path/exception_hooks.py", line 122, in <module>
# do_stuff()
# File "/home/some/path/exception_hooks.py", line 7, in do_stuff
# raise ValueError("Some error message")
# ValueError: Some error message</module>- 我们还可以给提示信息的某一部分设置颜色:
# pip install colorama
from colorama import init, Fore
init(autoreset=True)# Reset the color after every print
def exception_hook(exc_type, exc_value, tb):
local_vars = {}
while tb:
filename = tb.tb_frame.f_code.co_filename
name = tb.tb_frame.f_code.co_name
line_no = tb.tb_lineno
# Prepend desired color (e.g. RED) to line
print(f"{Fore.RED}File {filename} line {line_no}, in {name}")
local_vars = tb.tb_frame.f_locals
tb = tb.tb_next
print(f"{Fore.GREEN}Local variables in top frame: {local_vars}")除了上面介绍的例子,你还可以输出每一帧的局部变量,或者找到出现异常的行中所引用的变量。这些Exception Hooks已经很成熟了,相比于自定义Exception hooks,我建议你阅读下其他开发者的源码,学习下他们的设计思路。
- 输出每一帧的局部变量[1]
- 找到出现异常的行中所引用的变量[2]
第三方库中的Exception Hooks
自定义一个Exception Hook很有趣,但许多第三方库已经实现这一功能了。与其自己造轮子,不如看看其他优秀的工具。
- 首先,我个人最喜欢的是Rich,可以直接用pip进行安装,随后导入使用。如果你只想在一个例子中使用,可以这样做:python -m rich.traceback
# https://rich.readthedocs.io/en/latest/traceback.html # pip install rich # python -m rich.traceback from rich.traceback import install install(show_locals=True) do_stuff()# Raises ValueError

- better_exceptions也很受欢迎,我们需要先设置环境变量BETTER_EXCEPTIONS=1,再用pip安装。此外,如果你的TERM变量不是xterm,还要把SUPPORTS_COLOR设置为True。
# https://github.com/Qix-/better-exceptions # pip install better_exceptions # export BETTER_EXCEPTIONS=1 import better_exceptions better_exceptions.MAX_LENGTH = None # 检查你的 TERM 变量是否被设置为 `xterm`, 如果没有执行以下操作 # See issue: https://github.com/Qix-/better-exceptions/issues/8 better_exceptions.SUPPORTS_COLOR = True better_exceptions.hook() do_stuff()# Raises ValueError

- 使用最方便的库是pretty_errors,只需导入即可:
# https://github.com/onelivesleft/PrettyErrors/ # pip install pretty_errors import pretty_errors # 如果你对默认配置满意的话,则无需修改 pretty_errors.configure( filename_display= pretty_errors.FILENAME_EXTENDED, line_number_first = True, display_link= True, line_color= pretty_errors.RED + '> ' + pretty_errors.default_config.line_color, code_color= '' + pretty_errors.default_config.line_color, truncate_code = True, display_locals= True ) do_stuff()
除了直接导入外,上面的代码还显示了该库的一些可选配置。更多的配置可以查看这里:配置[3]

- IPython的ultratb模块
# https://ipython.readthedocs.io/en/stable/api/generated/IPython.core.ultratb.html # pip install ipython import IPython.core.ultratb # Also ColorTB, FormattedTB, ListTB, SyntaxTB sys.excepthook = IPython.core.ultratb.VerboseTB(color_scheme='Linux')# Other colors: NoColor, LightBG, Neutral do_stuff()

- stackprinter库
# https://github.com/cknd/stackprinter # pip install stackprinter import stackprinter stackprinter.set_excepthook(style='darkbg2') do_stuff()

结论
本文我们学习了如何自定义Exception Hooks,但我更推荐使用第三方库。你可以在本文介绍的第三方库中任选一个喜欢的,用到项目中。需要注意的是使用自定义Exception Hooks可能会丢失某些关键信息,例如:本文中的某些例子中,输出中缺少文件路径,在远程调试代码这无疑很不方便,因此,需要谨慎使用。
理论要掌握,实操不能落!以上关于《探索新方法:展示 Python 异常信息的方式与众不同》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
173 收藏
-
435 收藏
-
203 收藏
-
179 收藏
-
192 收藏
-
142 收藏
-
260 收藏
-
336 收藏
-
370 收藏
-
111 收藏
-
174 收藏
-
422 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习