关于python:如何区分ValueError的情况

How to differentiate between cases of ValueError

由于太多的python操作返回ValueError,我们如何区分它们?

示例:我希望一个iterable具有单个元素,并且我想获取它

  • a, = [1, 2]:ValueError:太多值无法解包
  • a, = []:ValueError:无法解包的值太少

如何区分这两种情况?例如

1
2
3
4
5
6
7
try:
    a, = lst
except ValueError as e:
    if e.too_many_values:
        do_this()
    else:
        do_that()

我意识到在这种特殊情况下,我可以使用长度/索引找到解决方法,但是要指出的是,经常出现类似的情况,我想知道是否有通用的方法。我也意识到我可以检查if 'too few' in message的错误消息,但似乎有点粗糙。


1
2
3
4
5
6
7
8
9
10
11
12
try:
    raise ValueError('my error')
except ValueError as e:

    # use str(), not repr(), see
    # https://stackoverflow.com/a/45532289/7919597

    x = getattr(e, 'message', str(e))

    if 'my error' in x:

        print('got my error')

(另请参阅如何在Python中正确获取异常消息)

但这毕竟不是一个干净的解决方案。

最好的办法是缩小try块的范围,以便只有一个可能。或不要依靠异常来检测那些错误情况。


这并不是真正的答案,因为它仅在您对引发异常的方式有一定控制权时才适用。由于异常只是对象,因此您可以添加其他对象/标记。并不是说这是一件伟大的事情或一种伟大的实现方式:

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
from enum import Enum

class ValueErrorType(Enum):
    HelloType = 0,
    FooType = 1


def some_func(string):
    if"Hello" in string:
        error = ValueError(""Hello" is not allowed in my strings!!!!")
        error.error_type = ValueErrorType.HelloType
        raise error
    elif"Foo" in string:
        error = ValueError(""Foo" is also not allowed!!!!!!")
        error.error_type = ValueErrorType.FooType
        raise error

try:
    some_func("Hello World!")
except ValueError as error:
    error_type_map = {
        ValueErrorType.HelloType: lambda: print("It was a HelloType"),
        ValueErrorType.FooType: lambda: print("It was a FooType")
    }
    error_type_map[error.error_type]()

我很想知道是否有某种方法可以实现此目标,但您无法控制它们的筹集方式。