The import
- VC Healy
- May 24, 2020
- 3 min read
Import-related module attributes The import machinery fills in these attributes on each module object during loading, based on the module’s spec, before the loader executes the module. __name__
The __name__ attribute must be set to the fully-qualified name of the module. This name is used to uniquely identify the module in the import system.
__loader__
The __loader__ attribute must be set to the loader object that the import machinery used when loading the module. This is mostly for introspection, but can be used for additional loader-specific functionality, for example getting data associated with a loader.
__package__
The module’s __package__ attribute must be set. Its value must be a string, but it can be the same value as its __name__. When the module is a package, its __package__ value should be set to its __name__. When the module is not a package, __package__ should be set to the empty string for top-level modules, or for submodules, to the parent package’s name.
This attribute is used instead of __name__ to calculate explicit relative imports for main modules, as defined in PEP 366.
It is expected to have the same value as __spec__.parent. Changed in version 3.6: The value of __package__ is expected to be the same as __spec__.parent.
__spec__
The __spec__ attribute must be set to the module spec that was used when importing the module. Setting __spec__ appropriately applies equally to modules initialized during interpreter startup. The one exception is __main__, where __spec__ is set to None in some cases. When __package__ is not defined, __spec__.parent is used as a fallback. New in version 3.4. Changed in version 3.6: __spec__.parent is used as a fallback when __package__ is not defined.
__path__
If the module is a package (either regular or namespace), the module object’s __path__ attribute must be set. The value must be iterable, but may be empty if __path__ has no further significance. If __path__ is not empty, it must produce strings when iterated over. More details on the semantics of __path__ are given below. Non-package modules should not have a __path__ attribute.
__file__
__cached__
__file__ is optional. If set, this attribute’s value must be a string. The import system may opt to leave __file__ unset if it has no semantic meaning (e.g. a module loaded from a database).
If __file__ is set, it may also be appropriate to set the __cached__ attribute which is the path to any compiled version of the code (e.g. byte-compiled file). The file does not need to exist to set this attribute; the path can simply point to where the compiled file would exist
It is also appropriate to set __cached__ when __file__ is not set. However, that scenario is quite atypical. Ultimately, the loader is what makes use of __file__ and/or __cached__. So if a loader can load from a cached module but otherwise does not load from a file, that atypical scenario may be appropriate.
module.__path__ By definition, if a module has a __path__ attribute, it is a package. A package’s __path__ attribute is used during imports of its subpackages. Within the import machinery, it functions much the same as sys.path, i.e. providing a list of locations to search for modules during import. However, __path__ is typically much more constrained than sys.path. __path__ must be an iterable of strings, but it may be empty. The same rules used for sys.path also apply to a package’s __path__, and sys.path_hooks (described below) are consulted when traversing a package’s __path__.
A package’s __init__.py file may set or alter the package’s __path__ attribute, and this was typically the way namespace packages were implemented prior to PEP 420. With the adoption of PEP 420, namespace packages no longer need to supply __init__.py files containing only __path__ manipulation code; the import machinery automatically sets __path__ correctly for the namespace package.
The import statement
The most common way to invoke the import machinery. Other related functions importlib.import_module() and built-in __import__()
import combines two operations.
Search for named module
# import calls __import__() for this with the appropriate parameters
Bind the result of the search name to a name in the local scope.
Direct calling of __import__ only performs the search and module creation operation.
There can be issues with this action as only import performs the binding operation.
If the named module cannot be found a ModuleNotFoundError is raised
import *
This will at first glance be thought to import all the functions from another module/package.
What it doesn't do, is import any fnction that's name starts with an _. This is the system of naming that allows Python to mark functions as private/local to that module. Thus these would not be imported.
There is a secondary attribute held in the module being imported that with explicitly limit the functions that can be exported by an import *.
__all__ statements can be drawn up at the top of the exporting module assigning a list with elements that are function names from the module that are allowed to be exported. Thus making all functions in that module private unless detailed in that list.
Σχόλια