¶Importing a nested module does not create a shim
You can import a nested module using the typical dot notation: import os.path. This creates a binding in the current file-global scope called os. You must access the imported nested module (and its contents) using its full path: os.path.join.
Nothing unexpected so far. But at this point, there are a few possibilities:
- os is just a shim object of some kind, and only contains the nested path module. You don't have access to any definitions in os unless you import explicitly that as well.
- os is the actual os package. You have access to all of its definitions, as well as the path submodule, but not to any other submodules, unless you import them.
- os is the actual os package. You have access to all of its definitions, the path submodule, and all other submodules in the package, but not any sub-submodules.
- os is the actual os package. You have access to all of its definitions, the path submodule, and all other submodules and sub-submodules (etc) in the package.
I can't find if it's explicitly documented anywhere, but it seems Python implements option (2): importing os.path also implicitly imports os, but not any other submodules unless you explicitly import them.
¶A false start
Note that I first tried with logging—I thought it would be a better test since it contains more than one submodule.
But! This is a false positive. This behavior occurs because logging.config itself imports logging.handlers!
Python 3.12.7 (main, Oct 1 2024, 11:15:50) [GCC 14.2.1 20240910] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import logging >>> logging <module 'logging' from '/usr/lib/python3.12/logging/__init__.py'> >>> logging.config Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: module 'logging' has no attribute 'config' >>> import logging.config >>> logging <module 'logging' from '/usr/lib/python3.12/logging/__init__.py'> >>> logging.Logger <class 'logging.Logger'> >>> logging.config <module 'logging.config' from '/usr/lib/python3.12/logging/config.py'> >>> logging.config.fileConfig <function fileConfig at 0x71a0d3dcdda0> >>> logging.handlers <module 'logging.handlers' from '/usr/lib/python3.12/logging/handlers.py'> >>> logging.handlers.WatchedFileHandler <class 'logging.handlers.WatchedFileHandler'>