多次尝试例外,但如果其中一个失败(最后),则会引发错误

use*_*ber 2 python exception python-3.x

所以我说了 3 个我想运行的函数。他们每个人都可能失败。我想try-except围绕它们构建:

  • 让 3 个中尽可能多的运行 AND
  • 如果其中任何一个失败,则在最后引发错误。这可能吗?

下面的代码由于操作 D 失败(中间失败),因此永远不会到达 E:

try:
    c = 3 + 6
    print(c)
except TypeError:
    raise TypeError("Wrong type provided in operation C")

try:
    d = 3 + '6'
    print(d)
except TypeError:
    raise TypeError("Wrong type provided in operation D")

try:
    e = 7 + 5
    print(e)
except TypeError:
    raise TypeError("Wrong type provided in operation E")
Run Code Online (Sandbox Code Playgroud)

tim*_*geb 5

def f1():
    print("f1")

def f2():
    raise TypeError
    print("f2")

def f3():
    print("f3")


err = None

for f in [f1, f2, f3]:
    try:
        f()
    except TypeError as e:
        # store first error
        if not err:
            err = e

if err:
    raise err
Run Code Online (Sandbox Code Playgroud)

输出:

f1
f3
[...]
TypeError
Run Code Online (Sandbox Code Playgroud)

如果你的函数带有参数,你可以循环

[(f1, f1_args, f1_kwargs), (f2, f2_args, f2_kwargs), (f3, f3_args, f3_kwargs)]
Run Code Online (Sandbox Code Playgroud)

受到评论的启发,我试图想出一个漂亮的上下文管理器,它在退出时以嵌套方式引发所有异常。欢迎评论。

class ErrorCollector:
    def __init__(self):
        self.errors = []

    def exec(self, f, suppress_types=None, *args, **kwargs):
        suppress_types = tuple(suppress_types) if suppress_types else ()

        try:
            return f(*args, **kwargs)
        except suppress_types as e:
            self.errors.append(e)

    def _raise_all(self, errors):
        if len(errors) == 1:
            raise errors[0]

        for e in errors:
            try:
                raise e
            except type(e):
                self._raise_all(errors[1:])

    def __enter__(self):
        return self

    def __exit__(self, exctype, excinst, exctb):
        if excinst is not None:
            self.errors.append(excinst)
        self._raise_all(self.errors)


def f1():
    print('f1')

def f2():
    raise TypeError('TypeError in f2')
    print('f2')

def f3():
    raise ValueError('ValueError in f3')
    print('f3')

def f4():
    raise TypeError('TypeError in f4')
    print('f4')

def f5():
    print('f5')

def f6():
    raise ZeroDivisionError('ZeroDivisionError in f6')
    print('f6')

def f7():
    print('f7')
Run Code Online (Sandbox Code Playgroud)

现在您可以使用:

suppress = [TypeError, ValueError]

with ErrorCollector() as ec:
    for f in (f1, f2, f3, f4, f5, f6, f7):
        ec.exec(f, suppress)
Run Code Online (Sandbox Code Playgroud)

输出:

f1
f5
[...]
TypeError: TypeError in f2
During handling of the above exception, another exception occurred:
[...]
ValueError: ValueError in f3
During handling of the above exception, another exception occurred:
[...]
TypeError: TypeError in f4
During handling of the above exception, another exception occurred:
[...]
ZeroDivisionError: ZeroDivisionError in f6
Run Code Online (Sandbox Code Playgroud)

请注意,由于未抑制,f7因此未执行。ZeroDivisionError