TGViewer
Находки в опенсорсе Находки в опенсорсе @opensource_findings · 12.6K subscribers
Post #965 10.1K
Находки в опенсорсе Free-Threading и итераторы: что могло пойти так? Недавно в питоне появилась новая фича (которую я вам пока не покажу), а я решил сделать новый формат – вопрос-загадку. Мы все знаем, что Free-Threading работает совсем по-другому, вместо одного глобального…
Настало время ответов!

Во-первых

Код из примера упадет с ValueError: generator already executing.
Почему так? Нельзя дважды запустить один и тот же генератор, даже в одном треде.

Самый простой пример:


def g():
i = next(me)
yield i

me = g()
next(me) # ValueError


Исходник:


static PySendResult // Objects/genobject.c
gen_send_ex(PyGenObject *gen, PyObject *arg, PyObject **presult)
{
int8_t frame_state = FT_ATOMIC_LOAD_INT8_RELAXED(gen->gi_frame_state);
// ...
if (frame_state == FRAME_EXECUTING) {
PyErr_SetString(PyExc_ValueError, "generator already executing");
return PYGEN_ERROR;
}
// ...
}


Во-вторых

Переиспользовать генераторы в разных тредах - особенно плохая идея. О чем теперь явно написано в документации. Данный паттерн не поддерживается во Free-Threading нативно. Корневая причина, для самых любопытных: https://github.com/python/cpython/issues/120496

PR: https://github.com/python/cpython/pull/148894
Документация: https://docs.python.org/3.15/library/threading.html#iterator-synchronization

Был добавлен способ вызова __next__ под локом (как правильно догадались в комментариях):


class serialize_iterator:
def __init__(self, iterable):
self._iterator = iter(iterable)
self._lock = Lock()
def __iter__(self):
return self
def __next__(self):
with self._lock:
return next(self._iterator)


Для того, чтобы код из оригинального примера заработал, нужно заменить iterator = producer(limit) на iterator = threading.serialize_iterator(producer(limit)). Есть еще декоратор @synchronized_iterator для определения threadsafe генераторов сразу.

Теперь - должно быть понятно, почему такая фича была добавлена.

Было ли интересно поковырять? Было ли сложно? :)
GitHub Sequence iterator thread-safety · Issue #120496 · python/cpython Bug report Bug description: Sequence iterators are not thread-safe under the free-threaded build. They'll sometimes be accessed with the same index. Here is a minimal repro: import concurrent.f...
  • 👍 69
  • 🔥 19
  • 🤯 10
  • ❤ 3
  • 🎉 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 →