You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sys.modules doc entry should reflect restrictions #56842
The sys.modules dict is a special object. It is the only variable of the CPython interpreter object that is exposed in the sys module[1]. Everything else in sys lives in the module. However, the modules dict lives in the interpreter object and is bound to the sys module separately. No other variable of the interpreter object gets this treatment.
This situation sets up an unexpected behavior for sys.modules. There are many places, mostly in Python/import.c, where the modules dict gets used and not by pulling from sys.modules. These places use interp->modules directly[2]. So if sys.modules is re-bound, the imp module is using/reporting an out of sync modules dict.
One could argue that re-binding a module global is risky and should be avoided. I agree. Here is the use case that prompted me to march ahead anyway:
I was writing some import related tests and wanted sys.modules to be returned to its initial state after each test. I realise that Lib/test/support.py provides CleanImport and others address this, but you have to provide the module names to clean up. This is an unfortunate hassle sometimes when several layers of imports happen during the import of the module you care about.
So the result was an exception when I tried importing an extension module, like "_sqlite3". This is because in importdl.h the new module is added to the dict returned by PyImport_GetModuleDict(), not to the one at sys.modules.
For now I am doing the following to get the same effect:
However, this is less efficient, sort of. I expect that the current direct use of interp->modules in the CPython code is [much?] more efficient than PySys_GetObject("modules") calls.
Proposal
In light of all this I recommend that either use of interp->modules be replaced by PySys_GetObject("modules") calls, or the sys module documentation[3] be updated to make clear that sys.modules should not be re-bound (in a CPython implementation detail note). I'm guessing that the first option is right out. The documentation addition would be just right.
[1] variables of the interpreter object found by grepping "interp->" in the CPython source:
modules
modules_by_index
next
codec_search_path
codec_search_cache
codec_error_registry
codecs_initialized
fscodec_initialized
modules_reloading
builtins
sysdict
tstate_head
tscdump
dlopenflags
[2] see PyImport_GetModuleDict() in Python/import.c
[3] http://docs.python.org/dev/library/sys.html#sys.modules
Would an implementation detail note be inappropriate here? I only ask because it looks like the imp module's use of interp->modules is implementation specific.
Activity
ericsnowcurrently commentedon Jul 25, 2011
The sys.modules dict is a special object. It is the only variable of the CPython interpreter object that is exposed in the sys module[1]. Everything else in sys lives in the module. However, the modules dict lives in the interpreter object and is bound to the sys module separately. No other variable of the interpreter object gets this treatment.
This situation sets up an unexpected behavior for sys.modules. There are many places, mostly in Python/import.c, where the modules dict gets used and not by pulling from sys.modules. These places use interp->modules directly[2]. So if sys.modules is re-bound, the imp module is using/reporting an out of sync modules dict.
One could argue that re-binding a module global is risky and should be avoided. I agree. Here is the use case that prompted me to march ahead anyway:
I was writing some import related tests and wanted sys.modules to be returned to its initial state after each test. I realise that Lib/test/support.py provides CleanImport and others address this, but you have to provide the module names to clean up. This is an unfortunate hassle sometimes when several layers of imports happen during the import of the module you care about.
So the result was an exception when I tried importing an extension module, like "_sqlite3". This is because in importdl.h the new module is added to the dict returned by PyImport_GetModuleDict(), not to the one at sys.modules.
For now I am doing the following to get the same effect:
However, this is less efficient, sort of. I expect that the current direct use of interp->modules in the CPython code is [much?] more efficient than PySys_GetObject("modules") calls.
Proposal
In light of all this I recommend that either use of interp->modules be replaced by PySys_GetObject("modules") calls, or the sys module documentation[3] be updated to make clear that sys.modules should not be re-bound (in a CPython implementation detail note). I'm guessing that the first option is right out. The documentation addition would be just right.
[1] variables of the interpreter object found by grepping "interp->" in the CPython source:
modules
modules_by_index
next
codec_search_path
codec_search_cache
codec_error_registry
codecs_initialized
fscodec_initialized
modules_reloading
builtins
sysdict
tstate_head
tscdump
dlopenflags
[2] see PyImport_GetModuleDict() in Python/import.c
[3] http://docs.python.org/dev/library/sys.html#sys.modules
ncoghlan commentedon Jul 25, 2011
+1 for making this limitation explicit. See the caveat on locals() [1] for an example of how to note this kind of restriction.
[1] http://docs.python.org/dev/library/functions.html#locals
ericsnowcurrently commentedon Jul 25, 2011
Would an implementation detail note be inappropriate here? I only ask because it looks like the imp module's use of interp->modules is implementation specific.
Here's a patch for Doc/library/sys.rst that adds the note.
[-]sys.modules gets special treatment[/-][+]sys.modules doc entry should reflect restrictions[/+]merwok commentedon Jul 29, 2011
The note’s spirit is good, but I think something more concise would do.
Side note: Please don’t mix up unrelated cosmetic changes in your diffs.
ericsnowcurrently commentedon Apr 18, 2012
The original motivator: http://mail.python.org/pipermail/python-dev/2011-July/112497.html
ericsnowcurrently commentedon Apr 18, 2012
also, bpo-14615 is related to making sys.modules authoritative.
ericsnowcurrently commentedon Feb 17, 2013
One proposal would lead to the sys module growing descriptors:
http://mail.python.org/pipermail/python-ideas/2013-January/019075.html
In that case, sys.modules could update the underlying interp->modules.
ericsnowcurrently commentedon Jun 25, 2013
bpo-17953 addressed part of this.
ericsnowcurrently commentedon Sep 4, 2017
We're dropping PyInterpreterState.modules (bpo-28411).