当前位置: 欣欣网 > 码农

用 PrettyError优雅的处理Python错误信息

2024-03-14码农

来自: 简讯Alfred

大家有没有觉 得编程更像是这样一种行为,我们可能会用 20 % 的时间将想法写入代码,然后用 80% 的时间来清除错误和修复漏洞。 错误信息肯定是我们每天都会看到的, 信息 可能非常 冗长, 这样 很难区分不同的部分并快速找到我们需要的信息 堆栈跟踪有 时也过于复杂,难以理解。 此外,除非我们覆 盖异常类,否则也很难自定义错误信息,这可能又会 让人不知所 措。

在本文中,我将介绍一个名为 PrettyError 的库,它可以帮助我们解决上述所有痛点以及更多问题。它有许多很酷的功能,可以简化我们的调试过程,帮助我们在编码工作中节省大量时间。

1. 安装和快速启动

像往常一样,安装 PrettyError 库非常简单。我们只需运行 pip 从 PyPI 获取即可。

pip install pretty_errors

快速入门

这可能是最快捷的快速入门指南。当我们想使用默认配置的程序库时,只需在编码前导入即可。

import pretty_errors

现在,让我们定义一个不带 try-except 的函数,以便以后手动创建一些错误。

defdivide(a, b):
return a / b

那么,让我们先看看没有 Pretty Errors 时的情况。我们将模拟除以零的错误。

divide(10)

这就是 Python 中的原始错误信息。然后,让我们通过简单的导入来启用 Pretty Error,并再次运行代码。

import pretty_errors
divide(10)

它已用颜色编码,并配有简化的指示器,如 stdin 和函数名称分隔符。

由于本文篇幅所限,无法演示颜色代码在实践中的作用。下图是 GitHub README 中的截图。

在上述场景中,您喜欢左边的(原始)还是右边的(高亮错误)?

2. 主要特点

该库能做的远不止我们在快速入门中展示的这些。在本节中,我将挑选一些关键功能进行演示。

2.1 配置颜色代码

PrettyError 允许我们自定义颜色代码。

例如,让我们在 Python 脚本文件 app.py 中输入以下代码。

import pretty_errors
open("non_existent_file.txt")

然后,让我们运行这个脚本看看会发生什么。

以上就是 PrettyError 中的默认颜色代码。如果我们想自定义代码呢?很简单,只需使用 pretty_error 模块中的 configure() 函数,如下所示。

import pretty_errors
pretty_errors.configure(
line_color = pretty_errors.BRIGHT_RED,
exception_color = pretty_errors.BRIGHT_MAGENTA,
exception_arg_color = pretty_errors.CYAN,
exception_file_color = pretty_errors.RED_BACKGROUND + pretty_errors.BRIGHT_WHITE
)
open("non_existent_file.txt")

让我们再次运行这个脚本文件。

有 16 种不同的错误信息输出类型,如 function_color、code_color 和 syntax_error_color,PrettyError 可以对它们进行自定义。

此外,你可能会注意到我使用了 PrettyError 提供的默认颜色枚举。共有 9 种不同的主色调,包括黑色、灰色、红色、绿色、黄色、蓝色、金黄色、青色和白色。每种颜色还带有前缀 BRIGHT_ 和后缀 _BACKGROUND,因此我们可以使用一系列不同的默认颜色。

除此之外,你可能会注意到我在上述配置代码中使用了组合颜色。

pretty_errors.RED_BACKGROUND + pretty_errors.BRIGHT_WHITE

这也是允许的,因此背景色和字体色可以一起用于特定的信息类型。由此可见,如果我们想自定义错误信息,PrettyError 提供了足够多的颜色代码选项。

2.2 添加时间戳

原始 Python 错误信息的一个缺点是不能在显示错误的同时显示时间戳。当然,常见的解决方案是在程序中添加日志模块。

但是,如果程序在完全未捕获和未知异常的情况下崩溃,日志记录解决方案通常也无法实现。此外,有时我们可能出于某种原因想使用一些轻量级的解决方案。

当然,只需添加以下配置,PrettyError 就能做到这一点。

import pretty_errors
pretty_errors.configure(
display_timestamp=1
)
open("non_existent_file.txt")

配置 display_timestamp 将在显示错误的同时显示一个时间戳,如下所示。

时间戳是 perf_counter 并不完全适合人类阅读。还有一种配置可以帮助我们自定义时间戳功能。下面是一个使用 datetime 模块获取当前时间戳的示例。由于配置将函数作为参数,因此最简单的方法就是传递一个 lambda 函数。

import pretty_errors
import datetime
pretty_errors.configure(
display_timestamp=1,
timestamp_function=lambda: datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
)
open("non_existent_file.txt")

当然,如果您想要非常个性化的时间格式,最好在配置之前定义函数,然后只传递函数名。

2.3 在错误中显示更多代码

原始 Python 错误信息的另一个限制是,它只能显示出错的代码行。 在发生错误的代码之前的其他代码可能是导致错误的关键因素。 除此之外,显示后面的代码也很有用,这样我们就能知道如果错误没有发生,将执行什么代码。

这可以在 PrettyError 中使用 lines_before 和 lines_after 配置来实现。

import pretty_errors
pretty_errors.configure(
lines_before=2,
lines_after=1
)
# The output shouldn't show this comment (lines before)
# The output should show this comment (lines before)
defcalculate(x):
return1 / x
# The output should show this comment (lines after)
# The output shouldn't show this comment (lines after)
defwrapper():
calculate(0)
wrapper()



请关注上述代码片段中的注释。根据配置前后的行数,我添加了一些注释,以显示错误信息中应显示哪一行代码。

我们还可以控制跟踪堆栈的级别。有时,当我们不关心主方法之前的堆栈情况时,这个功能会非常有用。因此,我们可以简化错误信息,帮助我们关注错误发生的具体位置。

这可以通过配置项 stack_depth 来实现。

import pretty_errors
pretty_errors.configure(
stack_depth=1
)
defcalculate(x):
return1 / x
defwrapper():
calculate(0)
wrapper()


因此,现在的堆栈深度更小了。

2.4 显示变量值

这是 Python 中最受欢迎的错误信息之一,但在原来的错误信息中却不见踪影。在开发过程中,当我们处理大多数 bug 时,经常需要使用调试工具来重现问题。

如果错误信息能告诉你变量的值是多少呢?也许在大多数情况下,我们可以直接排除故障!

在 PrettyError 中启用这一功能也非常简单,我们可以将 display_locals 配置项设置为 1。

import pretty_errors
pretty_errors.configure(
display_locals=1# Enable the display of local variables
)
defcalculate_divide(x, y):
return x / y
calculate_divide(10)


让我们运行这个脚本看一看。

错误信息告诉我们这是一个 ZeroDivisionError。如果我们查看变量 x 和 y 的输出,就会发现 y 的值为 0。

3.环境方面的最佳做法

实际上,我们有时可能希望错误信息非常冗长,但并非总是如此。就上文介绍的功能而言,在不同的环境中,启用或禁用这些功能的偏好也会有所不同。

因此,我们建议利用环境变量来控制 PrettyError 的行为。下面是一个例子。

import pretty_errors
import os
# Configure PrettyErrors based on the environment
if os.getenv('ENV') == 'development':
pretty_errors.configure(
stack_depth=0, # Show full stack
display_locals=1# Show local variables in development
)
else:
pretty_errors.configure(
stack_depth=1, # Show only 3 levels depth
display_locals=0# Hide local variables in production
)
# Main Program
defcalculate(x):
return1 / x
defwrapper():
calculate(0)
wrapper()



让我们用不同的环境变量运行脚本。 请注意,如果使用的是 Windows 操作系统,则应使用 set ENV=development。 当然,使用这种方法,您还可以针对不同的环境进行其他定制和配置。

在本文中,我介绍了 PrettyError。它旨在修正 Python 错误信息中存在的一些限制,确保错误信息更易于理解,从而提高开发和调试效率。 它有许多有用的功能,如彩色编码、包含时间戳、显示变量值和自定义堆栈跟踪。 当然,作为一种调试工具,我们可能需要考虑是否希望它在所有环境下都能工作。 因此,可以引入环境变量来解决这个问题。

加入知识星球【我们谈论数据科学】

600+小伙伴一起学习!