python / python/cpython

Allow libraries to opt-in to context variable inheritance by new threads

Ouverte
#154,562 0 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

interpreter-core type-feature
Langage dominant
Python
Étoiles
77.2k
Forks
35.9k
Métriques de merge des PR
Métriques de PR en attente

Description

Feature or enhancement

Proposal:

Provide a mechanism for a library to declare that the state it keeps in context variables should be inherited by newly started threads, without requiring the whole application to enable the thread_inherit_context flag and without requiring the code that creates threads to cooperate.

Libraries are encouraged to store formerly global or thread-local state in contextvars.ContextVar so the state is safe for asyncio tasks and free-threaded code. An example is numpy's printoptions, which moved from a module-level global to a context variable so that with numpy.printoptions(...) is isolated between concurrently running tasks.

This migration has a thread-visibility regression on builds where sys.flags.thread_inherit_context is false (the default for GIL-enabled builds). New threads start with an empty context, so a binding made by the starting thread is not visible in the worker thread and the state silently reverts to its default:

with numpy.printoptions(precision=2):
    # thread prints with default precision unless
    # thread_inherit_context is enabled
    threading.Thread(target=work).start()

When the state was a module-level global, worker threads always saw the current value. After moving to a context variable, they no longer do. This makes the migration a behavior change for existing threaded programs, which discourages libraries from adopting context variables at all.

The existing mechanisms are not usable by the library author:

  • -X thread_inherit_context=1 / PYTHON_THREAD_INHERIT_CONTEXT is process-wide and controlled by the application or end user, not by the library whose state is affected. A library cannot require every application embedding it to change interpreter flags, and enabling whole-context inheritance may be undesirable for unrelated reasons.
  • threading.Thread(context=...) requires the code constructing the thread to pass the context. Threads are typically created by application code, frameworks, or thread pools that know nothing about the library's context variables.

What is missing is a middle ground between "threads inherit nothing" and "threads inherit everything": a way for a library to opt its own state into inheritance across threading.Thread.start(), on a per-library (or per-variable) basis, regardless of the process-wide flag. This would let libraries convert global state to context-local state without regressing thread behavior, and would ease the eventual transition to thread_inherit_context defaulting to true, since libraries opting in today would see no behavior change when the default flips.

Explicitly supplied contexts (Thread(context=...)) should continue to behave as they do now.

Has this already been discussed elsewhere?

I have already discussed this feature proposal on Discourse

Links to previous discussion of this feature:

https://discuss.python.org/t/enabling-thread-inherit-context-and-context-aware-warnings-by-default-on-both-builds/108205

Linked PRs
  • gh-154564

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

L’issue mentionne threading.Thread.start(), Thread(context=...) et contextvars.ContextVar ; lisez d’abord ces points d’entrée ainsi que la PR liée gh-154564. Le travail est considéré comme terminé lorsqu’une bibliothèque peut inclure l’état sélectionné des variables de contexte dans l’héritage des threads nouvellement démarrés, tandis que le comportement explicite de Thread(context=...) et la sémantique du flag à l’échelle du processus restent inchangés.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
operating-systems
Type d'issue
Fonctionnalité
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
25/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.