Multiple interpreters in a Python process¶
While in most uses, you will only embed a single Python interpreter, thereare cases where you need to create several independent interpreters in thesame process and perhaps even in the same thread. Sub-interpreters allowyou to do that.
The “main” interpreter is the first one created when the runtime initializes.It is usually the only Python interpreter in a process. Unlike sub-interpreters,the main interpreter has unique process-global responsibilities like signalhandling. It is also responsible for execution during runtime initialization andis usually the active interpreter during runtime finalization. ThePyInterpreterState_Main() function returns a pointer to its state.
You can switch between sub-interpreters using thePyThreadState_Swap()function. You can create and destroy them using the following functions:
- typePyInterpreterConfig¶
Structure containing most parameters to configure a sub-interpreter.Its values are used only in
Py_NewInterpreterFromConfig()andnever modified by the runtime.Added in version 3.12.
Structure fields:
- intuse_main_obmalloc¶
If this is
0then the sub-interpreter will use its own“object” allocator state.Otherwise it will use (share) the main interpreter’s.If this is
0thencheck_multi_interp_extensionsmust be1(non-zero).If this is1thengilmust not bePyInterpreterConfig_OWN_GIL.
- intallow_fork¶
If this is
0then the runtime will not support forking theprocess in any thread where the sub-interpreter is currently active.Otherwise fork is unrestricted.Note that the
subprocessmodule still workswhen fork is disallowed.
- intallow_exec¶
If this is
0then the runtime will not support replacing thecurrent process via exec (e.g.os.execv()) in any threadwhere the sub-interpreter is currently active.Otherwise exec is unrestricted.Note that the
subprocessmodule still workswhen exec is disallowed.
- intallow_threads¶
If this is
0then the sub-interpreter’sthreadingmodulewon’t create threads.Otherwise threads are allowed.
- intallow_daemon_threads¶
If this is
0then the sub-interpreter’sthreadingmodulewon’t create daemon threads.Otherwise daemon threads are allowed (as long asallow_threadsis non-zero).
- intcheck_multi_interp_extensions¶
If this is
0then all extension modules may be imported,including legacy (single-phase init) modules,in any thread where the sub-interpreter is currently active.Otherwise only multi-phase init extension modules(seePEP 489) may be imported.(Also seePy_mod_multiple_interpreters.)This must be
1(non-zero) ifuse_main_obmallocis0.
- intgil¶
This determines the operation of the GIL for the sub-interpreter.It may be one of the following:
- PyInterpreterConfig_DEFAULT_GIL¶
Use the default selection (
PyInterpreterConfig_SHARED_GIL).
- PyInterpreterConfig_SHARED_GIL¶
Use (share) the main interpreter’s GIL.
- PyInterpreterConfig_OWN_GIL¶
Use the sub-interpreter’s own GIL.
If this is
PyInterpreterConfig_OWN_GILthenPyInterpreterConfig.use_main_obmallocmust be0.- PyInterpreterConfig_DEFAULT_GIL¶
- intuse_main_obmalloc¶
- PyStatusPy_NewInterpreterFromConfig(PyThreadState**tstate_p,constPyInterpreterConfig*config)¶
Create a new sub-interpreter. This is an (almost) totally separate environmentfor the execution of Python code. In particular, the new interpreter hasseparate, independent versions of all imported modules, including thefundamental modules
builtins,__main__andsys. Thetable of loaded modules (sys.modules) and the module search path(sys.path) are also separate. The new environment has nosys.argvvariable. It has new standard I/O stream file objectssys.stdin,sys.stdoutandsys.stderr(however these refer to the same underlyingfile descriptors).The givenconfig controls the options with which the interpreteris initialized.
Upon success,tstate_p will be set to the firstthread statecreated in the new sub-interpreter. This thread state isattached.Note that no actual thread is created; see the discussion of thread statesbelow. If creation of the new interpreter is unsuccessful,tstate_p is set to
NULL;no exception is set since the exception state is stored in theattached thread state, which might not exist.Like all other Python/C API functions, anattached thread statemust be present before calling this function, but it might be detached uponreturning. On success, the returned thread state will beattached.If the sub-interpreter is created with its ownGIL then theattached thread state of the calling interpreter will be detached.When the function returns, the new interpreter’sthread statewill beattached to the current thread andthe previous interpreter’sattached thread state will remain detached.
Added in version 3.12.
Sub-interpreters are most effective when isolated from each other,with certain functionality restricted:
PyInterpreterConfigconfig={.use_main_obmalloc=0,.allow_fork=0,.allow_exec=0,.allow_threads=1,.allow_daemon_threads=0,.check_multi_interp_extensions=1,.gil=PyInterpreterConfig_OWN_GIL,};PyThreadState*tstate=NULL;PyStatusstatus=Py_NewInterpreterFromConfig(&tstate,&config);if(PyStatus_Exception(status)){Py_ExitStatusException(status);}
Note that the config is used only briefly and does not get modified.During initialization the config’s values are converted into various
PyInterpreterStatevalues. A read-only copy of the configmay be stored internally on thePyInterpreterState.Extension modules are shared between (sub-)interpreters as follows:
For modules using multi-phase initialization,e.g.
PyModule_FromDefAndSpec(), a separate module object iscreated and initialized for each interpreter.Only C-level static and global variables are shared between thesemodule objects.For modules using legacysingle-phase initialization,e.g.
PyModule_Create(), the first time a particular extensionis imported, it is initialized normally, and a (shallow) copy of itsmodule’s dictionary is squirreled away.When the same extension is imported by another (sub-)interpreter, a newmodule is initialized and filled with the contents of this copy; theextension’sinitfunction is not called.Objects in the module’s dictionary thus end up shared across(sub-)interpreters, which might cause unwanted behavior (seeBugs and caveats below).Note that this is different from what happens when an extension isimported after the interpreter has been completely re-initialized bycalling
Py_FinalizeEx()andPy_Initialize(); in thatcase, the extension’sinitmodulefunctionis called again.As with multi-phase initialization, this means that only C-level staticand global variables are shared between these modules.
- PyThreadState*Py_NewInterpreter(void)¶
- Part of theStable ABI.
Create a new sub-interpreter. This is essentially just a wrapperaround
Py_NewInterpreterFromConfig()with a config thatpreserves the existing behavior. The result is an unisolatedsub-interpreter that shares the main interpreter’s GIL, allowsfork/exec, allows daemon threads, and allows single-phase initmodules.
- voidPy_EndInterpreter(PyThreadState*tstate)¶
- Part of theStable ABI.
Destroy the (sub-)interpreter represented by the giventhread state.The given thread state must beattached.When the call returns, there will be noattached thread state.All thread states associated with this interpreter are destroyed.
Py_FinalizeEx()will destroy all sub-interpreters thathaven’t been explicitly destroyed at that point.
A per-interpreter GIL¶
Added in version 3.12.
UsingPy_NewInterpreterFromConfig() you can createa sub-interpreter that is completely isolated from other interpreters,including having its own GIL. The most important benefit of thisisolation is that such an interpreter can execute Python code withoutbeing blocked by other interpreters or blocking any others. Thus asingle Python process can truly take advantage of multiple CPU coreswhen running Python code. The isolation also encourages a differentapproach to concurrency than that of just using threads.(SeePEP 554 andPEP 684.)
Using an isolated interpreter requires vigilance in preserving thatisolation. That especially means not sharing any objects or mutablestate without guarantees about thread-safety. Even objects that areotherwise immutable (e.g.None,(1,5)) can’t normally be sharedbecause of the refcount. One simple but less-efficient approach aroundthis is to use a global lock around all use of some state (or object).Alternately, effectively immutable objects (like integers or strings)can be made safe in spite of their refcounts by making themimmortal.In fact, this has been done for the builtin singletons, small integers,and a number of other builtin objects.
If you preserve isolation then you will have access to proper multi-corecomputing without the complications that come with free-threading.Failure to preserve isolation will expose you to the full consequencesof free-threading, including races and hard-to-debug crashes.
Aside from that, one of the main challenges of using multiple isolatedinterpreters is how to communicate between them safely (not breakisolation) and efficiently. The runtime and stdlib do not provideany standard approach to this yet. A future stdlib module would helpmitigate the effort of preserving isolation and expose effective toolsfor communicating (and sharing) data between interpreters.
Bugs and caveats¶
Because sub-interpreters (and the main interpreter) are part of the sameprocess, the insulation between them isn’t perfect — for example, usinglow-level file operations likeos.close() they can(accidentally or maliciously) affect each other’s open files. Because of theway extensions are shared between (sub-)interpreters, some extensions may notwork properly; this is especially likely when using single-phase initializationor (static) global variables.It is possible to insert objects created in one sub-interpreter intoa 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 importoperations executed by such objects may affect the wrong (sub-)interpreter’sdictionary of loaded modules. It is equally important to avoid sharingobjects from which the above are reachable.
Also note that combining this functionality withPyGILState_* APIsis delicate, because these APIs assume a bijection between Python thread statesand OS-level threads, an assumption broken by the presence of sub-interpreters.It is highly recommended that you don’t switch sub-interpreters between a pairof matchingPyGILState_Ensure() andPyGILState_Release() calls.Furthermore, extensions (such asctypes) using these APIs to allow callingof Python code from non-Python created threads will probably be broken when usingsub-interpreters.
High-level APIs¶
- typePyInterpreterState¶
- Part of theLimited API (as an opaque struct).
This data structure represents the state shared by a number of cooperatingthreads. Threads belonging to the same interpreter share their moduleadministration and a few other internal items. There are no public members inthis structure.
Threads belonging to different interpreters initially share nothing, exceptprocess state like available memory, open file descriptors and such. The globalinterpreter lock is also shared by all threads, regardless of to whichinterpreter they belong.
Changed in version 3.12:PEP 684 introduced the possibilityof aper-interpreter GIL.See
Py_NewInterpreterFromConfig().
- PyInterpreterState*PyInterpreterState_Get(void)¶
- Part of theStable ABI since version 3.9.
Get the current interpreter.
Issue a fatal error if there is noattached thread state.It cannot return NULL.
Added in version 3.9.
- int64_tPyInterpreterState_GetID(PyInterpreterState*interp)¶
- Part of theStable ABI since version 3.7.
Return the interpreter’s unique ID. If there was any error in doingso then
-1is returned and an error is set.The caller must have anattached thread state.
Added in version 3.7.
- PyObject*PyInterpreterState_GetDict(PyInterpreterState*interp)¶
- Return value: Borrowed reference. Part of theStable ABI since version 3.8.
Return a dictionary in which interpreter-specific data may be stored.If this function returns
NULLthen no exception has been raised andthe caller should assume no interpreter-specific dict is available.This is not a replacement for
PyModule_GetState(), whichextensions should use to store interpreter-specific state information.The returned dictionary is borrowed from the interpreter and is valid untilinterpreter shutdown.
Added in version 3.8.
- typedefPyObject*(*_PyFrameEvalFunction)(PyThreadState*tstate,_PyInterpreterFrame*frame,intthrowflag)¶
Type of a frame evaluation function.
Thethrowflag parameter is used by the
throw()method of generators:if non-zero, handle the current exception.Changed in version 3.9:The function now takes atstate parameter.
Changed in version 3.11:Theframe parameter changed from
PyFrameObject*to_PyInterpreterFrame*.
- _PyFrameEvalFunction_PyInterpreterState_GetEvalFrameFunc(PyInterpreterState*interp)¶
Get the frame evaluation function.
See thePEP 523 “Adding a frame evaluation API to CPython”.
Added in version 3.9.
- void_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState*interp,_PyFrameEvalFunctioneval_frame)¶
Set the frame evaluation function.
See thePEP 523 “Adding a frame evaluation API to CPython”.
Added in version 3.9.
Low-level APIs¶
All of the following functions must be called afterPy_Initialize().
Changed in version 3.7:Py_Initialize() now initializes theGILand sets anattached thread state.
- PyInterpreterState*PyInterpreterState_New()¶
- Part of theStable ABI.
Create a new interpreter state object. Anattached thread state is not needed,but may optionally exist if it is necessary to serialize calls to thisfunction.
Raises anauditing event
cpython.PyInterpreterState_Newwith no arguments.
- voidPyInterpreterState_Clear(PyInterpreterState*interp)¶
- Part of theStable ABI.
Reset all information in an interpreter state object. There must beanattached thread state for the interpreter.
Raises anauditing event
cpython.PyInterpreterState_Clearwith no arguments.
- voidPyInterpreterState_Delete(PyInterpreterState*interp)¶
- Part of theStable ABI.
Destroy an interpreter state object. Thereshould not be anattached thread state for the target interpreter. The interpreterstate must have been reset with a previous call to
PyInterpreterState_Clear().
Advanced debugger support¶
These functions are only intended to be used by advanced debugging tools.
- PyInterpreterState*PyInterpreterState_Head()¶
Return the interpreter state object at the head of the list of all such objects.
- PyInterpreterState*PyInterpreterState_Main()¶
Return the main interpreter state object.
- PyInterpreterState*PyInterpreterState_Next(PyInterpreterState*interp)¶
Return the next interpreter state object afterinterp from the list of allsuch objects.
- PyThreadState*PyInterpreterState_ThreadHead(PyInterpreterState*interp)¶
Return the pointer to the first
PyThreadStateobject in the list ofthreads associated with the interpreterinterp.
- PyThreadState*PyThreadState_Next(PyThreadState*tstate)¶
Return the next thread state object aftertstate from the list of all suchobjects belonging to the same
PyInterpreterStateobject.