TGViewer
Находки в опенсорсе Находки в опенсорсе @opensource_findings · 12.6K subscribers
Post #953 9.54K
PEP 828: async yield from и состояние асинхронных генераторов в питоне

PEP: https://peps.python.org/pep-0828
Обсуждение: https://discuss.python.org/t/pep-828-supporting-yield-from-in-asynchronous-generators/106459
Код: https://github.com/python/cpython/pull/145716

В питон хотят добавить async yield from. И у меня есть много разных мыслей.

Во-первых, оно реально иногда удобно. Во-вторых, реально консистентно визуально и синтаксически с синхронными генераторами:


async def agenerator():
yield 1
yield 2

async def main():
async yield from agenerator()


С другой стороны: https://pyfound.blogspot.com/2024/06/python-language-summit-2024-limiting-yield-in-async-generators.html

> Guido van Rossum lamented that this was "yet another demonstration that async generators were a bridge too far. Could we have a simpler PEP that proposes to deprecate and eventually remove from the language asynchronous generators, just because they're a pain and tend to spawn more complexity".

> Zac had no objections to a PEP deprecating async generators¹. Zac continued, "while static analysis is helpful in some cases, there are inevitably cases that it misses which kept biting us... until we banned all async generators in our codebase".

И вроде бы на примере выше оно выглядит нормально. Но давайте чуть глубже посмотрим.

Кстати, недавно наш коллега – Сергей Мирянов – добавил секцию "Async generators best practices" в доку asyncio.
Всем советую: https://docs.python.org/3.15/library/asyncio-dev.html#asynchronous-generators-best-practices

Если вы можете найти в данном коде 4 ошибки, то можете не читать доку. Остальным обязательно.


import asyncio
work_done = False

async def cursor():
try:
yield 1
finally:
assert work_done

async def rows():
global work_done
try:
yield 2
finally:
await asyncio.sleep(0.1) # immitate some async work
work_done = True

async def main():
async for c in cursor():
async for r in rows():
break
break

asyncio.run(main())


Какие проблемы там подсвечены?
1. Явное использование aclosing(agen) контекста для закрытия AsyncGenerator, иначе может пропасть стадия "уборки за собой", а сам генератор может остаться живым
2. Порядок очистки ресурсов в асинхронных генераторах может быть не таким, как вы думаете
3. Запуск асинхронных генераторов без event loop - плохая идея
4. Итерация асинхронного генератора из двух разных тасок = ошибка

Так вот! Стоит ли углубляться туда?

Обсуждение: что вы думаете про асинхронные генераторы и их развитие? Можете ли честно сказать, что понимаете, как они работают? Можете найти баги с asyncio.CanceledError и очисткой состояния без запуска кода? Я - нет.

| Поддержать | YouTube | GitHub | Чат |
  • ❤ 32
  • 👍 16
  • 😢 6
  • 🔥 1
  • 🤔 1
More from @opensource_findings
  1. Sep 15, 2026PEPы в Python окончательно вышли из-под контроля Давайте посмотрим, что происходит с ПЕПам…
  2. Sep 10, 2026Большая бесплатная конференция в Нижнем Новгороде 17 октября Регистрация: https://itgorky.…
  3. Sep 1, 2026Post #985
  4. Aug 24, 2026JIT могут удалить из CPython! PEP-836: https://peps.python.org/pep-0836 JIT в CPython имее…
  5. Aug 18, 2026Как AWS у опенсорсера пакеты отжимал Нерегулярная рубрика "посмотрите, что творится!". Дан…
  6. Aug 14, 2026Какие уникальные фичи есть в django-modern-rest? Иногда, когда я добавляю какие-то фичи в…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →