Hello,

I came across what seems like either a bug in the import system or a gap in its 
documentation, so I'd like to run it by folks here to see if I should submit a 
bug report. If there's somewhere else more appropriate to discuss this, please 
let me know.

If you import A.B, then remove A from sys.modules and import A.B again, the 
newly-loaded version of A will not contain an attribute referring to B. Using 
"collections.abc" as an example submodule from the standard library:

>>> import sys
>>> import collections.abc
>>> del sys.modules['collections']
>>> import collections.abc
>>> collections.abc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'collections' has no attribute 'abc'

This behavior seems quite counter-intuitive to me: why should the fact that B 
is already loaded prevent adding a reference to it to A? It also goes against 
the general principle that "import FOO" makes the expression "FOO" 
well-defined; for example PLR 5.7 states that "'import XXX.YYY.ZZZ' should 
expose 'XXX.YYY.ZZZ' as a usable expression". Finally, it violates the 
"invariant" stated in PLR 5.4.2 that if 'A' and 'A.B' both appear in 
sys.modules, then A.B must be defined and refer to sys.modules['A.B'].

On the other hand, PLR 5.4.2 also states that "when a submodule is loaded using 
any mechanism... a binding is placed in the parent module's namespace to the 
submodule object", which is consistent with the behavior above, since the 
second import of A.B does not actually "load" B (only retrieve it from the 
sys.modules cache). So perhaps Python is working as intended here, and there is 
an unwritten assumption that if you unload a module from the cache, you must 
also unload all of its submodules. If so, I think this needs to be added to the 
documentation (which currently places no restrictions on how you can modify 
sys.modules, as far as I can tell).

This may be an obscure corner case that is unlikely to come up in practice (I 
imagine few people need to modify sys.modules), but it did actually cause a bug 
in a project I work on, where it is necessary to uncache certain modules so 
that they can be reloaded. I was able to fix the bug some other way, but I 
think it would still be worthwhile to either make the import behavior more 
consistent (so that 'import A.B' always sets the B attribute of A) or add a 
warning in the documentation about this case. I'd appreciate any thoughts on 
this!

Thanks,
Daniel
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/VIPXZRK3OJNSVNSZSAJ7CO6QFC2RX27W/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to