__exit __()(上下文管理器)中的exc_value参数是字符串而不是Exception(Python 2.6)

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

我试图搞乱上下文管理器,并且在使用Python 2.6运行代码时感到有些惊讶。 实际上,exc_value参数似乎是一个字符串而不是一个例外。

一些代码来解决这个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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:

1
2
3
4
5
<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:

1
2
3
4
5
6
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:

1
2
3
4
5
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中的新功能:PEP 343:with语句

  • Python 2文档:object.__exit__(self, exc_type, exc_value, traceback)


这是Python 2.6中的一个错误,请参阅问题7853.它已针对Python 2.7a3修复,但从未向后移植到2.6分支。

换句话说,你没有做错任何事,Python做到了。

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