在Python中单独处理相同类型的异常

Handling same type exceptions separately in Python

说我有以下四个变量:

1
2
3
4
>>> f1 = (print, 1, 2 ,3 ,4)
>>> f2 = (exit, 1, 2 ,3 ,4)
>>> f3 = (1, 2, 3, 4)
>>> f4 = 4

在一个假设的程序中,我希望每个变量都包含一个元组,其第一个项应该是函数的名称,其后续项应该按顺序表示函数的参数。

我可以像这样调用以这种方式存储的函数:

1
2
>>> f1[0](*f1[1:])
1 2 3 4

但是,大多数这些变量都不是例外格式,我希望能够在try / except块中封装它们,以便处理这些情况。

现在,即使f2f3f4的函数调用因完全不同的原因而中断,它们都会抛出相同的异常,即TypeError

1
2
3
4
5
6
7
8
9
10
11
12
>>> f2[0](*f2[1:])
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
TypeError: __call__() takes from 1 to 2 positional arguments but 5 were given
>>> f3[0](*f3[1:])
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
>>> f4[0](*f4[1:])
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
TypeError: 'int' object is not subscriptable

这样做一般:

1
2
3
4
try:
    f[0](*f[1:])
except TypeError:
    # handle exception

不会为我提供足够的信息来相应地处理每个例外。

在Python中区分相同类型的不同异常的正确方法是什么?


因此,您需要使用与function(*tuple)不同的调用方法。 下面是一个函数fun_apply的示例,它使用位置和关键字参数调用特定函数。 它添加了一个显式检查,以确保args是可迭代的,kwargs继承自collection.Mapping

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from collections import Mapping

def fun_apply(f, args=None, kwargs=None):                                                                                
    if args is None:
        args = []
    if kwargs is None:
        kwargs = {}

    try:
        args = iter(args)
    except TypeError:
        # handle args being non-iterable
        pass

    if isinstance(kwargs, collections.Mapping):
        pass
    else:
        # handle kwargs being a non-mapping
        pass

    if hasattr(f, '__call__'):
        pass
    else:
        # handle f being non-callable
        pass

    try:
        f(*args, **kwargs)
    except TypeError as e:
        raise TypeError(e)

另一个选项是显式处理message字符串,但这可能会产生意想不到的后果,并且错误消息本身可能在Python版本之间有所不同。