在 Python 中收集和报告多个异常的惯用方式

Posted

技术标签:

【中文标题】在 Python 中收集和报告多个异常的惯用方式【英文标题】:Idiomatic way to collect & report multiple exceptions in Python 【发布时间】:2012-04-10 03:57:54 【问题描述】:

人们曾经在 Python 中使用什么来一次捕获、记录和报告多个数据验证错误?

我正在使用 Python 3 构建一个应用程序,它首先验证输入数据,然后对其进行处理。第一步报告错误是程序预期功能的一部分,所以我不希望我的验证器放弃第一个异常。特别是,数据是表格的,我希望能够返回 - 而不是引发 - 表格中每一行未验证的异常。

forum discussion from a couple of years ago 考虑了多种解决方案,包括以下对我来说似乎最干净的解决方案:

errors = []
for item in data:
    try:
        process(item)
    except ValidationError as e:
        errors.append(e)
if errors:
    raise MultipleValidationErrors(errors)

MultipleValidationErrors 类将有一个适当的__str__ 方法来列出有关其中所有ValidationErrors 的有用信息。

其他人建议使用traceback 模块,但由于我要捕获的异常是数据验证错误而不是程序错误,这似乎不合适。不过,加入logging 模块可能是合适的。

【问题讨论】:

也许this question 会有所帮助 @inspectorG4dget:这个问题是关于捕获多种类型的异常;这个是关于捕获同一异常类型的多个实例。 您列出的代码将起作用,如果它符合您的要求,或者您可以使用 traceback 模块提供更多信息,正如您所提到的。或者,您可以将异常对象保存在数据结构中以供以后使用,或执行许多其他操作。这完全取决于您对响应异常的要求是什么,这在您的问题中并不清楚。 @Aaron-Watters 我的目标是,一旦我处理了所有传入的数据,我就可以打印所有的错误,每行传入的数据一行错误。 (更具体地说,由于我分别编写库和用户界面,我的库会将错误的数据结构返回给用户界面,用户界面可以做任何它想做的事情。CLI 会将错误打印到stdout,而 GUI将提供一些交互式表格界面。) 太糟糕了,论坛帖子实际上并没有讨论多种解决方案。相反,它是 OP 解决方案,然后在制表符和空格上纠缠不清。 【参考方案1】:

我在 C++ 和 Python 中都使用过这个习惯用法。当您想要的是异常而不是日志消息时,这是我所知道的最干净的解决方案。它的缺点是组合异常通常占用线性空间,这在处理具有许多错误的大型数据集时可能会出现问题。

【讨论】:

独立阅读时,此答案似乎缺少其上下文。我不知道你指的是什么成语。 @ThorSummoner 我认为 larsmans 指的是 OP 如何收集列表中的不同异常,然后引发包含该列表的单个异常。【参考方案2】:

我遵循错误列表方法,但将其包含在这样的对象中:

class Multi_Error(Exception):
    def __init__(self, errors: list[Exception]) -> None:
        self.errors = errors
        super().__init__(self.errors)

    def __str__(self) -> str:
        return "\n".join([str(x) for x in self.errors])

【讨论】:

以上是关于在 Python 中收集和报告多个异常的惯用方式的主要内容,如果未能解决你的问题,请参考以下文章

在 F# 中“合并”多个相同长度的列表的惯用方式?

在 sbt 0.13 中使用 .sbt 文件编写多项目构建的惯用方式

惯用的 Python:'times' 循环

SQLAlchemy,以惯用的 Python 方式进行可序列化事务隔离和重试

一次循环遍历 Javascript 数组多个元素的惯用方法是啥?

Clojure 中的惯用错误处理