mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	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
					
				
					 1 changed files with 35 additions and 17 deletions
				
			
		| 
						 | 
				
			
			@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue