Как имитировать повышение Python 3 в Python 2?

Python 3 имеет аккуратный

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

синтаксис, который позволяет вызвать последующее исключение без потери контекста. Лучшая аналогия, которую я мог придумать в Python 2, это

raise AnotherException((e,'I give up')), None, sys.exc_info()[2]

где (e,'') - это уродливый хак, чтобы включить имя исходного исключения в сообщение. Но разве нет лучшего способа?


person Tobias Kienzler    schedule 05.12.2014    source источник
comment
Вы могли бы сделать просто raise без каких-либо аргументов, но я не думаю, что вы могли бы изменить тип на AnotherException, если бы вы это сделали.   -  person Kevin    schedule 05.12.2014
comment
@Kevin Я знаю, это просто упрощение - в более реалистичном случае это было бы что-то вроде исключения «файл не найден», и его отказоустойчивость также дает сбой, что приводит к другому исключению с каким-то другим сообщением, но исходное исключение должно быть законсервированный   -  person Tobias Kienzler    schedule 05.12.2014
comment
Я не думаю, что Python 2 обеспечивает надлежащую поддержку чего-либо подобного. Я полагаю, вы могли бы обернуть свой уродливый хак в функцию reraise() или что-то в этом роде. Учитывая график выпуска 2.8, вы можете подумать о переходе на 3.x. У вас есть какие-либо зависимости только для 2.x?   -  person Kevin    schedule 05.12.2014
comment
@Kevin hg.python.org/peps/ rev/ :P В настоящее время основной причиной, по которой я использую Python 2.7, является PythonXY (Windows), но я также спрашиваю из любопытства   -  person Tobias Kienzler    schedule 08.12.2014


Ответы (2)


В raise_from. python-future.org/quickstart.html" rel="noreferrer">python-future; просто установите его

pip install future

и импортировать для использования

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)

ОБНОВИТЬ

Пакет совместимости six также поддерживает raise_from, начиная с версии 1.9 (выпущенной в 2015 году). Он используется так же, как и выше.

person tutuDajuju    schedule 23.04.2015
comment
Привет. raise_from в six на самом деле имитирует простой подъем (exec) в python2, поэтому он не ведет себя как python 3 :( - person bbaja42; 16.01.2017
comment
Да, raise_from в six имитирует простой рейз. Но reraise, тоже из six, сработало. См. пример по этой ссылке: python-future.org/compatible_idioms.html или в моем предложенном решение. - person waltersantosf; 20.03.2017

Вместо использования 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)
person waltersantosf    schedule 20.03.2017