#python #coroutine #finally
#python #сопрограмма #наконец
Вопрос:
class DemoException(Exception):
"""An exception type for the demonstration."""
def demo_exc_handling():
print('-> coroutine started')
while True:
try:
x = yield
except DemoException: # <1>
print('*** DemoException handled. Continuing...')
else: # <2>
print('-> coroutine received: {!r}'.format(x))
finally:
print('-> 1111111111coroutine ending')
raise RuntimeError('This line should never run.')
if __name__ == '__main__':
exc_coro = demo_exc_handling()
next(exc_coro)
exc_coro.send(11)
Я получаю следующий вывод:
-> coroutine started
-> coroutine received: 11
-> 1111111111coroutine ending
-> 1111111111coroutine ending
Я хочу знать, почему оператор finally выполняется дважды?
Я был бы очень благодарен за любую помощь.
Ответ №1:
Он печатается дважды, потому что предложение finally выполняется, даже если основная программа завершается.
Сопрограмма выдает результат во второй раз, когда основная программа завершается
Давайте выведем номер итерации и добавим пару распечаток, чтобы увидеть его
class DemoException(Exception):
"""An exception type for the demonstration."""
pass
def demo_exc_handling():
print('-> coroutine started')
i = 1
while True:
try:
print(f"iteration {i}")
x = yield i
except DemoException: # <1>
print('*** DemoException handled. Continuing...')
else: # <2>
print('-> coroutine received: {!r}'.format(x))
finally:
print('-> 1111111111coroutine ending')
i = 1
raise RuntimeError('This line should never run.')
if __name__ == '__main__':
exc_coro = demo_exc_handling()
print("initialised")
y = next(exc_coro)
print(f"got {y}")
exc_coro.send(11)
выдает
initialised
-> coroutine started
iteration 1
got 1
-> coroutine received: 11
-> 1111111111coroutine ending
iteration 2
-> 1111111111coroutine ending
Комментарии:
1. Спасибо за ответ. После прочтения вашего ответа, могу ли я понять это так: когда основная программа завершается, сопрограмма завершается либо. поскольку сопрограмма приостанавливается в yield, где находится в блоке try-except-finally, она выполнит предложение finally, а затем завершится.
Ответ №2:
Это не имеет ничего общего с сопрограммами или исключениями. Просто генератор будет воспроизводить нормально:
def demo_exc_handling():
print('-> coroutine started')
while True:
try:
x = yield
finally:
print('-> 1111111111coroutine ending')
raise RuntimeError('This line should never run.')
if __name__ == '__main__':
exc_coro = demo_exc_handling()
next(exc_coro)
next(exc_coro)
Вот результат:
-> coroutine started
-> 1111111111coroutine ending
-> 1111111111coroutine ending
То, что вы, вероятно, хотели сделать, это иметь цикл while ВНУТРИ try-finally:
def demo_exc_handling():
print('-> coroutine started')
try:
while True:
x = yield
finally:
print('-> 1111111111coroutine ending')
raise RuntimeError('This line should never run.')
который вместо этого выводит
-> coroutine started
-> 1111111111coroutine ending
Комментарии:
1. Это не отвечает на вопрос
2. Да, это так. Автор изменил порядок двух циклов. Он выполняется дважды, потому что циклы расположены не в том порядке, в котором их считает автор. Предложение «finally» всегда выполняется при завершении «try», что происходит дважды.
3. «Предложение «finally» всегда выполняется при завершении «try» » мне помогает. Спасибо.