Skip to content

Commit 4dce0fc

Browse files
Clarify about the relationship between OS threads, Python threads, and interpreters.
1 parent 9ccc743 commit 4dce0fc

File tree

1 file changed

+38
-23
lines changed

1 file changed

+38
-23
lines changed

Doc/reference/executionmodel.rst

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -453,40 +453,55 @@ specific to Python::
453453

454454
When a Python program starts, it looks exactly like that, with one
455455
of each. The process has a single global runtime to manage Python's
456-
process-global resources. Each Python thread has all the state it needs
457-
to run Python code (and use any supported C-API) in its OS thread.
458-
Depending on the implementation, this probably includes the current
459-
exception and the Python call stack.
460-
461-
In between the global runtime and the thread(s) lies the interpreter.
462-
It completely encapsulates all of the non-process-global runtime state
463-
that the interpreter's Python threads share. For example, all its
464-
threads share :data:`sys.modules`. Every Python thread belongs to a
465-
single interpreter and runs using that shared state. The initial
466-
interpreter is known as the "main" interpreter, and the initial thread,
467-
where the runtime was initialized, is known as the "main" thread.
456+
process-global resources. The runtime may grow to include multiple
457+
interpreters and each interpreter may grow to include multiple Python
458+
threads. The initial interpreter is known as the "main" interpreter,
459+
and the initial thread, where the runtime was initialized, is known
460+
as the "main" thread.
461+
462+
An interpreter completely encapsulates all of the non-process-global
463+
runtime state that the interpreter's Python threads share. For example,
464+
all its threads share :data:`sys.modules`, but each interpreter has its
465+
own :data:`sys.modules`.
468466

469467
.. note::
470468

471469
The interpreter here is not the same as the "bytecode interpreter",
472-
which is what runs in each thread, executing compiled Python code.
470+
which is what regularly runs in threads, executing compiled Python code.
471+
472+
A Python thread represents the state necessary for the Python runtime
473+
to *run* in an OS thread. It also represents the execution of Python
474+
code (or any supported C-API) in that OS thread. Depending on the
475+
implementation, this probably includes the current exception and
476+
the Python call stack. The Python thread always identifies the
477+
interpreter it belongs to, meaning the state it shares
478+
with other threads.
479+
480+
.. note::
481+
482+
Here "Python thread" does not necessarily refer to a thread created
483+
using the :mod:`threading` module.
484+
485+
Each Python thread is associated with a single OS thread, which is where
486+
it can run. In the opposite direction, a single OS thread can have many
487+
Python threads associated with it. However, only one of those Python
488+
threads is "active" in the OS thread at time. The runtime will operate
489+
in the OS thread relative to the active Python thread.
473490

474-
Every Python thread is associated with a single OS thread, which is
475-
where it runs. However, multiple Python threads can be associated with
476-
the same OS thread. For example, an OS thread might run code with a
477-
first interpreter and then with a second, each necessarily with its own
478-
Python thread. Still, regardless of how many are *associated* with
479-
an OS thread, only one Python thread can be actively *running* in
480-
an OS thread at a time. Switching between interpreters means
481-
changing the active Python thread.
491+
For an interpreter to be used in an OS thread, it must have a
492+
corresponding active Python thread. Thus switching between interpreters
493+
means changing the active Python thread. An interpreter can have Python
494+
threads, active or inactive, for as many OS threads as it needs. It may
495+
even have multiple Python threads for the same OS thread, though at most
496+
one can be active at a time.
482497

483498
Once a program is running, new Python threads can be created using the
484499
:mod:`threading` module (on platforms and Python implementations that
485500
support threads). Additional processes can be created using the
486501
:mod:`os`, :mod:`subprocess`, and :mod:`multiprocessing` modules.
487502
You can run coroutines (async) in the main thread using :mod:`asyncio`.
488-
Interpreters can be created using the :mod:`concurrent.interpreters`
489-
module.
503+
Interpreters can be created and used with the
504+
:mod:`concurrent.interpreters` module.
490505

491506

492507
.. rubric:: Footnotes

0 commit comments

Comments
 (0)