来自 __exit__()(上下文管理器)的 exc_value 参数是字符串而不是异常(Python 2.6)

exc_value parameter from __exit__() (context manager) is string instead of Exception (Python 2.6)

我试图弄乱上下文管理器,当 运行 我的代码使用 Python 2.6 时,我感到有点惊讶。事实上,exc_value 参数似乎是一个字符串而不是异常。

一些代码来强调这个问题:

import sys

class contextmanager(object):

    def __enter__(self):
        pass

    def __exit__(self, type_, value, traceback):
        assert (type_ is None) == (value is None)
        if value is not None:
            print(type(value))


if __name__ == '__main__':
    print(sys.version_info)
    with contextmanager():
        __name_ # should trigger name exception

与 Python 2.7 :

<type 'exceptions.NameError'>                       # GOOD
Traceback (most recent call last):
  File "test_conman.py", line 17, in <module>
    __name_
NameError: name '__name_' is not defined

与 Python 3.2 :

sys.version_info(major=3, minor=2, micro=3, releaselevel='final', serial=0)
<class 'NameError'>                       # GOOD
Traceback (most recent call last):
  File "test_conman.py", line 17, in <module>
    __name_
NameError: name '__name_' is not defined

与 Python 2.6 :

(2, 6, 7, 'final', 0)
<type 'str'>                       # BAD
Traceback (most recent call last):
  File "test_conman.py", line 17, in <module>
    __name_
NameError: name '__name_' is not defined

我的理解是 exc_value 应该总是例外。 我做错了什么吗? 我有什么误解吗? 这是一个已知问题吗?

参考资料

这是 Python 2.6 中的错误,请参阅 issue 7853。它已为 Python 2.7a3 修复,但从未向后移植到 2.6 分支。

换句话说,你没有做错,Python做错了。

不幸的是,除了处理您在 2.6 中没有异常实例而只有字符串值这一事实之外,没有真正的解决方法。