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

37

有哪些方法可以在Python中一次性捕获、记录和报告多个数据验证错误?

我正在使用Python 3构建一个应用程序,首先验证输入数据,然后处理它。第一步报告错误是程序预期功能的一部分,因此我不希望我的验证器在遇到第一个异常时就放弃。特别是,这些数据是表格形式的,我希望能够针对每行未经验证的表格返回而不是引发异常。

一篇几年前的论坛讨论仔细探讨了多种解决方案,包括以下看起来最为简洁的方法:

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 模块是合适的。


1
也许 这个问题 会有帮助 - inspectorG4dget
4
那个问题是关于捕获多种类型的异常,而这个问题是关于捕获同一异常类型的多个实例。 - Fred Foo
你列出的代码如果能够实现你想要的功能,那么它就可以工作。另外,你也可以使用traceback模块来提供更多的信息,正如你所提到的那样。或者,你可以将异常对象保存在数据结构中以备后用,或者进行其他许多操作。这一切都取决于你对异常响应的要求,而这些要求从你的问题中并不清楚。 - Aaron Watters
@Aaron-Watters 我的目标是,一旦我处理完所有传入的数据,我可以打印出所有错误,每行传入数据对应一行错误。更具体地说,由于我将库和用户界面分开编写,我的库将返回错误的数据结构给用户界面,用户界面可以根据需要进行操作。命令行界面会将错误打印到stdout,而图形用户界面则会提供一些交互式表格界面。 - wkschwartz
很遗憾,论坛帖子实际上并没有讨论多种解决方案。相反,它只是讨论了原始问题的解决方案,然后深入探讨了制表符与空格的区别。 - Randy
2个回答

9

我曾在C++和Python中使用过这个习语。它是我所知道的最干净的解决方案,当你想要的是一个异常而不是日志消息时。缺点是普遍情况下合并异常占用线性空间,当处理具有许多错误的大型数据集时可能会有问题。


5
这个回答似乎缺少上下文,单独阅读时不清楚你在指什么成语。 - ThorSummoner
2
@ThorSummoner 我认为larsmans指的是OP如何将不同的异常收集到一个列表中,然后引发包含该列表的单个异常。 - Pedro

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])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接