在 Python 3 中捕获 KeyError 消息

Catching KeyError message in Python 3

我无法在 Python 3(更具体地说是 3.5.3)的 KeyError 中捕获消息。

输入:

try:
    raise KeyError('some error message')
except KeyError as e:
    if str(e) == 'some error message':
        print('Caught error message')
    else:
        print("Didn't catch error message")

输出:

Didn't catch error message

奇怪的是,同样的事情适用于 IndexError

输入:

try:
    raise IndexError('some index error message')
except IndexError as e:
    if str(e) == 'some index error message':
        print('Caught IndexError message')
    else:
        print("Didn't catch IndexError message")

输出:

Caught IndexError message

此外,这个问题似乎是 Python 3 特有的,因为您可以在 Python 2.

中获取 message 属性

输入:

try:
    raise KeyError('some error message')
except KeyError as e:
    if e.message == 'some error message':
        print 'Caught error message'
    else:
        print "Didn't catch error message"

输出:

Caught error message

我通过检查我的错误消息是否在错误字符串中解决了我的问题:

输入:

try:
    raise KeyError('some error message')
except KeyError as e:
    if 'some error message' in str(e):
        print('Caught error message')
    else:
        print("Didn't catch error message")

输出:

Caught error message

有人能解释一下为什么这行得通但检查相等性却不行吗?

编辑:

正如 KGSH 指出的那样,str(e) 实际上是带有单引号的 'some error message'

@阿尔达: (因为我不能发表评论)

用这个迷你代码测试后:

try:
    raise KeyError('some error message')
except KeyError as e:
    print (str(e))
    print ('some error message')
    print (str(e) == 'some error message')

这是输出:

Caught error message
'some error message'
some error message
False

所以区别在于引号。

编辑:我希望有人帮助我更好地格式化它。

此行为在 the source code 中得到了完美解释:

static PyObject *
KeyError_str(PyBaseExceptionObject *self)
{
    /* If args is a tuple of exactly one item, apply repr to args[0].
       This is done so that e.g. the exception raised by {}[''] prints
         KeyError: ''
       rather than the confusing
         KeyError
       alone.  The downside is that if KeyError is raised with an explanatory
       string, that string will be displayed in quotes.  Too bad.
       If args is anything else, use the default BaseException__str__().
    */