Может ли исключение возникнуть в операторе try/except, не пропуская остальную часть предложения try?

Предположим, следующий код:

try:
    code_a
    code_b
    code_c
except:
    pass

Если ошибка возникает в code_b, то она будет обнаружена except и будет запущена только code_a. Есть ли способ обеспечить запуск code_c?

Я полагаю:

try: 
    code_a
except: 
    pass
try: 
    code_b
except: 
    pass
try: 
    code_c
except: 
    pass

это не правильный путь.


person Randy Sterbentz    schedule 01.07.2020    source источник
comment
Вы сами пробовали? Если нет, что вы пробовали?   -  person AverageJoe9000    schedule 01.07.2020
comment
Я думаю, что ваша единственная ставка - использовать несколько операторов try, так как если возникнет какая-либо ошибка, вы автоматически перейдете к блоку исключений. Возможно, включить обработку ошибок внутри каждой функции a, b и c и определить состояние на основе возвращаемого значения, вернуть -1, если возникнет ошибка, и 1 в противном случае и сравнить все три значения. Я не думаю, что вы ищете блок finally, поскольку он не будет обрабатывать какие-либо возникающие ошибки, он просто вызывает функцию независимо от того, возникло исключение или нет. Я надеюсь, что это помогло!   -  person Marsilinou Zaky    schedule 01.07.2020
comment
Также другим способом сделать это, но НЕ рекомендуется, является использование eval, поэтому используйте функцию, которая принимает cmd в качестве аргумента, а тело функции в основном представляет собой попытку eval (cmd), кроме прохода исключения, и все ваши команды в списке и прокручивайте их, этот метод не может быть применен ко всем случаям, хотя зависит от вашей программы   -  person Marsilinou Zaky    schedule 01.07.2020
comment
Делает ли finally то, что вы хотите?   -  person Karl Knechtel    schedule 01.07.2020
comment
также проверьте оператор with в Python (stackoverflow.com/a/3012565/2480947). Часто это проще, чем использовать блок try   -  person Nick    schedule 02.07.2020
comment
@MarsilinouZaky Мне нравится твоя вторая идея! Определение функции с помощью eval() в операторе try-except кажется кратким решением этой проблемы (хотя я думаю, что eval() иногда может быть туманным).   -  person Randy Sterbentz    schedule 02.07.2020


Ответы (2)


Краткий ответ на ваш вопрос в заголовке: «Нет». Остальная часть блока try: не будет выполняться после исключения.

Как вы заметили, вы можете поместить code_a, code_b и code_c в свои собственные блоки try: и обрабатывать ошибки отдельно.

Вы спросили, может ли code_c работать, даже если code_b вызвало исключение.

Опция 1

Поместите code_c полностью вне блока try::

try:
    code_a
    code_b
except:
    pass
code_c

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

try:
    code_a
    code_b
except:
    return False
code_c
return True

Если code_a или code_b вызывают исключение, code_c не будет выполняться.

Вариант 2

Используйте блок finally::

try:
    code_a
    code_b
except:
    return False
finally:
    code_c
return True

Если code_c находится в блоке finally:, он гарантированно выполнится независимо от того, есть ли исключение.

Если исключения нет, code_c выполняется после code_a и code_b.

Если есть исключение, return False будет работать, как и ожидалось, НО code_c втиснется и выполнится непосредственно перед возвратом функции. Это связано с тем, что гарантировано выполнение.

Полный пример

def ham():
    print('Ham please')


def eggs():
    print('Eggs please')
    raise NoEggsException


class NoEggsException(Exception):
    pass


def spam():
    print('Spam Spam Spam Spam Spam!')


def order():
    try:
        ham()
        eggs()
    except NoEggsException:
        print('    ...no eggs :(')
        return False
    finally:
        spam()
    return True


if __name__ == '__main__':
    order_result = order()
    print(f'Order complete: {order_result}')

При запуске, как написано, eggs() вызывает исключение. Результат выглядит следующим образом:

Ham please
Eggs please
    ...no eggs :(
Spam Spam Spam Spam Spam!
Order complete: False

Обратите внимание, что spam() (в блоке finally:) выполняется, несмотря на то, что в блоке except: есть return False.

Вот что происходит, когда raise NoEggsException закомментирован или удален:

Ham please
Eggs please
Spam Spam Spam Spam Spam!
Order complete: True

Обратите внимание, что вы получаете спам (и многое другое spam) в любом случае.

person Nick    schedule 01.07.2020
comment
Спасибо за подробный ответ! (А также урок истории спама) Ваша первая строка в основном ответила на мой вопрос. - person Randy Sterbentz; 02.07.2020

Вы можете использовать наконец:

try:
    print(1)
    print(some nonexistent variable)
except:
    pass
finally:
    print(3)

Это напечатает 1 и 3

person BossaNova    schedule 01.07.2020
comment
Я не думаю, что это точное использование finally. Может быть, вы можете выполнить его за пределами блока try. - person Austin; 01.07.2020
comment
Я думаю, это не то, что он спросил. Он просит запустить код c, d, e и т. д. после исключения в коде b. Наконец используется как закрытие файлов и т.д. - person Imran; 01.07.2020