Обработка исключений Python внутри с блоком - PullRequest
0 голосов
/ 06 июня 2018

В следующем коде что-то не так с оператором with и обработкой исключений в python3?Если нет, как правильно записать ожидаемый результат?

from contextlib import contextmanager

@contextmanager
def test():
    print("Hello")
    yield
    print("goodbye")

try:
    with test():
        print("inside test")
        raise KeyError
except KeyError:
    print("KeyError")
else:
    print("else")
finally:
    print("finally")

, и результат будет

Hello
inside test
KeyError
finally

, а я ожидаю результат будет:

Hello
inside test
goodbye
KeyError
finally

, который, как мне кажется, другие люди пишут аналогичным образом в надежде, что файл будет закрыт, когда возникнет исключение во время обработки файла.

Мой python3версия:

Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.version)
3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609]

1 Ответ

0 голосов
/ 06 июня 2018

Исключение из блока, управляемого оператором с , распространяется в ваш диспетчер контекста генератора через generator.throw(), как показано в PEP 343: «Генератор декоратора», что вызывает исключение в момент, когда генератор был приостановлен.Другими словами, вы должны обернуть yield в попытку / исключение или попытку / окончание:

@contextmanager
def test():
    print("Hello")
    try:
        # The block of the with statement executes when the generator yields
        yield

    finally:
        print("goodbye")

Чтобы процитировать официальную документацию по теме:

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

...