bpo-39161: Document multi-phase init modules under Py_NewInterpreter() (GH-17896)
\+ this also adds a stronger warning against sharing objects between (sub-)interpreters. https://bugs.python.org/issue39161
This commit is contained in:
parent
f3e5e95669
commit
6c5d661342
|
@ -1230,15 +1230,31 @@ function. You can create and destroy them using the following functions:
|
|||
single: Py_FinalizeEx()
|
||||
single: Py_Initialize()
|
||||
|
||||
Extension modules are shared between (sub-)interpreters as follows: the first
|
||||
time a particular extension is imported, it is initialized normally, and a
|
||||
(shallow) copy of its module's dictionary is squirreled away. When the same
|
||||
extension is imported by another (sub-)interpreter, a new module is initialized
|
||||
and filled with the contents of this copy; the extension's ``init`` function is
|
||||
not called. Note that this is different from what happens when an extension is
|
||||
imported after the interpreter has been completely re-initialized by calling
|
||||
:c:func:`Py_FinalizeEx` and :c:func:`Py_Initialize`; in that case, the extension's
|
||||
``initmodule`` function *is* called again.
|
||||
Extension modules are shared between (sub-)interpreters as follows:
|
||||
|
||||
* For modules using multi-phase initialization,
|
||||
e.g. :c:func:`PyModule_FromDefAndSpec`, a separate module object is
|
||||
created and initialized for each interpreter.
|
||||
Only C-level static and global variables are shared between these
|
||||
module objects.
|
||||
|
||||
* For modules using single-phase initialization,
|
||||
e.g. :c:func:`PyModule_Create`, the first time a particular extension
|
||||
is imported, it is initialized normally, and a (shallow) copy of its
|
||||
module's dictionary is squirreled away.
|
||||
When the same extension is imported by another (sub-)interpreter, a new
|
||||
module is initialized and filled with the contents of this copy; the
|
||||
extension's ``init`` function is not called.
|
||||
Objects in the module's dictionary thus end up shared across
|
||||
(sub-)interpreters, which might cause unwanted behavior (see
|
||||
`Bugs and caveats`_ below).
|
||||
|
||||
Note that this is different from what happens when an extension is
|
||||
imported after the interpreter has been completely re-initialized by
|
||||
calling :c:func:`Py_FinalizeEx` and :c:func:`Py_Initialize`; in that
|
||||
case, the extension's ``initmodule`` function *is* called again.
|
||||
As with multi-phase initialization, this means that only C-level static
|
||||
and global variables are shared between these modules.
|
||||
|
||||
.. index:: single: close() (in module os)
|
||||
|
||||
|
@ -1264,14 +1280,16 @@ process, the insulation between them isn't perfect --- for example, using
|
|||
low-level file operations like :func:`os.close` they can
|
||||
(accidentally or maliciously) affect each other's open files. Because of the
|
||||
way extensions are shared between (sub-)interpreters, some extensions may not
|
||||
work properly; this is especially likely when the extension makes use of
|
||||
(static) global variables, or when the extension manipulates its module's
|
||||
dictionary after its initialization. It is possible to insert objects created
|
||||
in one sub-interpreter into a namespace of another sub-interpreter; this should
|
||||
be done with great care to avoid sharing user-defined functions, methods,
|
||||
instances or classes between sub-interpreters, since import operations executed
|
||||
by such objects may affect the wrong (sub-)interpreter's dictionary of loaded
|
||||
modules.
|
||||
work properly; this is especially likely when using single-phase initialization
|
||||
or (static) global variables.
|
||||
It is possible to insert objects created in one sub-interpreter into
|
||||
a namespace of another (sub-)interpreter; this should be avoided if possible.
|
||||
|
||||
Special care should be taken to avoid sharing user-defined functions,
|
||||
methods, instances or classes between sub-interpreters, since import
|
||||
operations executed by such objects may affect the wrong (sub-)interpreter's
|
||||
dictionary of loaded modules. It is equally important to avoid sharing
|
||||
objects from which the above are reachable.
|
||||
|
||||
Also note that combining this functionality with :c:func:`PyGILState_\*` APIs
|
||||
is delicate, because these APIs assume a bijection between Python thread states
|
||||
|
|
Loading…
Reference in New Issue