threading.local в примере: почему выводится "missing"

threading.local в примере: почему выводится "missing"

@python_quiz

Разберем этот квиз

Коротко: в примере используется threading.local — отдельное пространство атрибутов для каждого потока. Код создаёт атрибут только в главном потоке, а в новом потоке этот атрибут отсутствует, поэтому используется значение по умолчанию в getattr.

Исходный код

python

Что здесь происходит — пошагово

  1. Создаётся объект store = local(). Это не обычный контейнер атрибутов: у каждого потока у этого объекта своё набор атрибутов.
  2. В основном потоке устанавливается store.x = 'main'. Этот атрибут хранится в пространстве атрибутов именно главного потока.
  3. Создаётся и запускается новый поток. Он получает тот же объект store, но для него пространство атрибутов пустое (пока что).
  4. Внутри нового потока вызывается getattr(store, 'x', 'missing'). Поскольку в этом потоке атрибут x не установлен, getattr возвращает заданное значение по умолчанию: 'missing'.
  5. В результате на вывод идёт строка missing.

Анализ вариантов ответов

  • Выведет: main

Поскольку атрибут x был установлен в главном потоке, на первый взгляд кажется, что другой поток может его прочитать. Но threading.local обеспечивает независимые наборы атрибутов для каждого потока, поэтому этот вариант неверен для данного кода.

  • Выведет: missing

Этот вариант соответствует тому, что реально произойдёт: в новом потоке атрибут x отсутствует, getattr с третьим аргументом возвращает значение по умолчанию ('missing').

  • Выведет: ошибка AttributeError

Ошибки не возникает, потому что используется getattr с аргументом по умолчанию. Если бы код делал доступ через store.x внутри нового потока без try/except, тогда действительно могла бы появиться AttributeError. Но в данном коде аварии не будет.

  • Поведение не определено, может быть main или missing

Поведение детерминировано: threading.local даёт отдельные пространства атрибутов для потоков, так что результат будет predictable — 'missing' при приведённом порядке операций. Нет гонки между созданием атрибута и чтением в другом потоке в данном коде, потому что атрибут устанавливается до старта потока.

Небольшие модификации и демонстрации

Гарантировать, что поток завершился, и увидеть вывод явно:

python

Если вы хотите, чтобы поток видел значение 'main', нужно передать значение явно или поставить глобальную переменную (не рекомендуется для синхронизации), либо установить атрибут внутри самого потока:

python

Или использовать общий (не thread-local) контейнер:

python

Вывод

threading.local создаёт независимые наборы атрибутов для каждого потока. В представленном коде атрибут x установлен только в главном потоке, а чтение в дочернем потоке возвращает значение по умолчанию, указанное в getattr. Для обмена данными между потоками используйте явную передачу значений, общие структуры данных с синхронизацией или другие механизмы межпоточного взаимодействия.

Report Page