Генератор можно остановить.
def gen():
try:
yield 1
yield 2
finally:
print('END')
g = gen()
print(next(g)) # выведет '1'
g.close() # выведет 'END'
Обрати внимание на три момента:
1. Нельзя использовать yield при обработке GeneratorExit
Если в блоке finally попытаться сделать yield, возникнет ошибка RuntimeError:
def gen():
try:
yield 1
finally:
yield 3 # ошибка!
g = gen()
next(g)
g.close() # RuntimeError
2. Исключение не выбрасывается, если генератор ещё не запускался
В этом случае генератор просто переходит в состояние остановлен, но finally не выполняется:
def gen():
try:
yield 1
finally:
print('END')
g = gen()
g.close() # ничего не выводит
print(list(g)) # выведет '[]'
3. close() ничего не делает, если генератор уже завершён
Если генератор полностью отработал, close() не вызывает finally повторно и просто игнорируется:
def gen():
try:
yield 1
yield 2
finally:
print('END')
g = gen()
print(list(g)) # ['1', '2']
print('Closing now')
g.close()
# Вывод:
# END
# [1, 2]
# Closing now
👉 @BookPython