I think a code example would make this most clear:
Python 3.8.9 (default, Apr 13 2022, 08:48:06)
[Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.path.exists('/'). // importing submodule is not necessary
True
>>> import unittest
>>> unittest.mock.MagicMock().
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'unittest' has no attribute 'mock'
>>> import unittest.mock. // importing submodule *is* necessary here
>>> unittest.mock.MagicMock()
<MagicMock id='4314421952'>
For unittest.mock
, I needed to import the submodule, but this wasn't the case for os.path
. What's the underlying mechanism that determines when this works? Does this have to do with namespace packages?
More broadly, when does Python search for submodules? This blog post says:
When Python sees that a module doesn't have a specified attribute, it considers the attribute to be a submodule and tries to import it. So if module defines func and Class but not submodule, Python will try to import module.submodule.
but I'm not certain how credible this is. If they are right, why doesn't that work for unittest.mock
?
To whoever closed this question as a duplicate, the linked question doesn't answer how or when python searches for submodules (does it ever?). Also this applies to circumstances beyond os.path
:
This answer explains that for importing os
automatically adds os.path
to sys.modules
. I've experienced this in at least one other case as well however.
Using the cognitojwt
package I found that I could run:
>>> import cognitojwt
>>> cognitojwt.token_utils.get_unverified_claims
without raising an attribute error. I checked the __init__.py
file, but didn't see any manual manipulation of sys.modules
so I suspect there's something more going on.