如何在Python 2中模仿Python 3的引发?

Tob*_*ler 21 exception raise traceback python-2.7 python-3.x

Python 3很整洁

try:
    raise OneException('sorry')
except OneException as e:
    # after a failed attempt of mitigation:
    raise AnotherException('I give up') from e
Run Code Online (Sandbox Code Playgroud)

允许在不丢失上下文的情况下引发后续异常的语法.我在Python 2中可以提出的最好的比喻是

raise AnotherException((e,'I give up')), None, sys.exc_info()[2]
Run Code Online (Sandbox Code Playgroud)

(e,'')是一个丑陋的黑客,它将原始异常的名称包含在消息中.但是不是有更好的方法吗?

tut*_*uju 22

raise_from蟒蛇未来有一个; 只需安装它

pip install future
Run Code Online (Sandbox Code Playgroud)

并导入使用

from future.utils import raise_from
# or: from six import raise_from

class FileDatabase:
    def __init__(self, filename):
        try:
            self.file = open(filename)
        except IOError as exc:
            raise_from(DatabaseError('failed to open'), exc)
Run Code Online (Sandbox Code Playgroud)

UPDATE

兼容性包six还支持raise_from1.9版(2015年发布).它以与上述相同的方式使用.

  • 你好。`six` 中的 raise_from 实际上模仿了 python2 中的普通 raise(exec) ,所以它没有得到 python 3 的行为:( (3认同)
  • 是的,`six` 中的 `raise_from` 模仿了普通的加注。但是同样来自“6”的“再加注”奏效了。请参阅此链接中的示例:http://python-future.org/compatible_idioms.html 或我建议的解决方案。 (2认同)

wal*_*osf 6

而不是使用six.raise_from,尝试使用six.reraise,如本页所述:

http://python-future.org/compatible_idioms.html

from six import reraise as raise_ 
# or from future.utils import raise_

traceback = sys.exc_info()[2]
raise_(ValueError, "dodgy value", traceback)
Run Code Online (Sandbox Code Playgroud)