Могу ли я получить исключение из блока finally в python? - PullRequest
31 голосов
/ 23 октября 2009

В моем скрипте есть предложение try / finally. Можно ли получить точное сообщение об ошибке из условия finally?

Ответы [ 5 ]

63 голосов
/ 23 октября 2009

Нет, в finally время sys.exc_info - все-Нет, было ли исключение или нет.Использование:

try:
  whatever
except:
  here sys.exc_info is valid
  to re-raise the exception, use a bare `raise`
else:
  here you know there was no exception
finally:
  and here you can do exception-independent finalization
11 голосов
/ 23 октября 2009

Блок finally будет выполняться независимо от того, было ли сгенерировано исключение или нет, поэтому, как указывает Джош, вы, скорее всего, не захотите обрабатывать его там.

Если вам действительно нужно значение исключения, которое было сгенерировано, то вы должны перехватить исключение в блоке except и либо обработать его соответствующим образом, либо повторно вызвать его, а затем использовать это значение в блоке finally. - с ожиданием, что он, возможно, никогда не был установлен, если не возникло исключение во время выполнения.

import sys

exception_name = exception_value = None

try:
    # do stuff
except Exception, e:
    exception_name, exception_value = sys.exc_info()[:2]
    raise   # or don't -- it's up to you
finally:
    # do something with exception_name and exception_value
    # but remember that they might still be none
3 голосов
/ 24 декабря 2016

На самом деле, другие ответы немного расплывчаты. Итак, позвольте мне уточнить это. Вы всегда можете вызвать sys.exc_info () из блока finally. Тем не менее, его вывод будет варьироваться в зависимости от того, было ли действительно возбуждено исключение.

import sys

def f(i):

    try:
        if i == 1:
            raise Exception
    except Exception as e:
        print "except -> " + str(sys.exc_info())
    finally:
        print "finally -> " + str(sys.exc_info())

f(0)
f(1)

>>> 
finally -> (None, None, None)
except -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x029438F0>)
finally -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x029438F0>)

Таким образом, вы всегда можете узнать в блоке finally, было ли вызвано исключение, если это функция первого уровня. Но sys.exc_info () будет вести себя иначе, когда длина стека вызовов превышает 1, как показано в примере ниже. Для получения дополнительной информации см. Как работает sys.exc_info ()?

import sys

def f(i):

    try:
        if i == 1:
            raise Exception
    except Exception as e:
        print "except -> " + str(sys.exc_info())
    finally:
        print "finally -> " + str(sys.exc_info())

def f1(i):
    if i == 0:
        try:
            raise Exception('abc')
        except Exception as e:
            pass

    f(i)

f1(0)
f1(1)

>>> 
finally -> (<type 'exceptions.Exception'>, Exception('abc',), <traceback object at 0x02A33940>)
except -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x02A33990>)
finally -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x02A33990>)

Надеюсь, это проясняет ситуацию.

2 голосов
/ 23 октября 2009

Вы захотите сделать это в предложении кроме, а не в конце.

См .: http://www.doughellmann.com/articles/Python-Exception-Handling/

0 голосов
/ 18 февраля 2018

Просто определите пустую переменную для возможного исключения перед try except блоком:

import sys

exception = None

try:
    result = 1/0
except ZeroDivisionError as e:
    exception = sys.exc_info()  # or "e"
finally:
    if exception:
        print(exception)
    else:
        print('Everything is fine')

Проверено на Python 3.6

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...