tgoop.com/BookPython/3606
Last Update:
Обычно вы взаимодействуете с генератором, запрашивая данные с помощью next(gen)
. В Python 3 вы также можете отправлять значения обратно в генератор с помощью g.send(x)
. Но существует техника, которой вы, вероятно, не пользуетесь каждый день, а возможно, и вовсе не знаете: выбрасывание исключений внутри генератора.
С помощью gen.throw(e)
можно выбросить исключение в той точке, где генератор gen
приостановлен — то есть на инструкции yield
. Если генератор обрабатывает это исключение, gen.throw(e)
возвращает следующее значение, полученное через yield
(или выбрасывает StopIteration
, если генератор завершён). Если генератор не перехватывает исключение, оно пробрасывается обратно к вызывающему коду.
def gen():
try:
yield 1
except ValueError:
yield 2
g = gen()
next(g)
# Out: 1
g.throw(ValueError)
# Out: 2
g.throw(RuntimeError('TEST'))
# RuntimeError: TEST
Эта техника позволяет более точно управлять поведением генератора — не только передавать данные внутрь, но и, например, сообщать о проблемах со значениями, полученными через
yield
. Однако такие случаи бывают редко, и встретить g.throw
в дикой природе почти невозможно.Тем не менее, декоратор
@contextmanager
из модуля contextlib
использует именно такую технику, позволяя коду внутри контекста перехватывать исключения.
from contextlib import contextmanager
@contextmanager
def atomic():
print('BEGIN')
try:
yield
except Exception:
print('ROLLBACK')
else:
print('COMMIT')
with atomic():
print('ERROR')
raise RuntimeError()
BEGIN
ERROR
ROLLBACK
👉@BookPython
BY Библиотека Python разработчика | Книги по питону
Share with your friend now:
tgoop.com/BookPython/3606