Updated writeup about import statements to strongly recommend absolute imports from main modules
This commit is contained in:
parent
a218af0b7f
commit
09618837a9
80
pep-0338.txt
80
pep-0338.txt
|
@ -180,39 +180,67 @@ deleting ``sys.argv[0]`` (which refers to the ``runpy`` module itself)
|
|||
and then invokes ``run_module(sys.argv[0], run_name="__main__",
|
||||
alter_sys=True)``.
|
||||
|
||||
Relative Imports
|
||||
================
|
||||
Import Statements and the Main Module
|
||||
=====================================
|
||||
|
||||
2.5b1 showed an annoying interaction between this PEP and PEP 328 -
|
||||
explicit relative imports don't work from a main module, because
|
||||
relative imports rely on ``__name__`` to determine the current module's
|
||||
position in the package hierarchy.
|
||||
The release of 2.5b1 showed a surprising (although obvious in
|
||||
retrospect) interaction between this PEP and PEP 328 - explicit
|
||||
relative imports don't work from a main module. This is due to
|
||||
the fact that relative imports rely on ``__name__`` to determine
|
||||
the current module's position in the package hierarchy. In a main
|
||||
module, the value of ``__name__`` is always ``'__main__'``, so
|
||||
explicit relative imports will always fail (as they only work for
|
||||
a module inside a package).
|
||||
|
||||
Accordingly, the operation of ``run_module()`` was modified so that
|
||||
another special variable ``__module_name__`` was defined in the
|
||||
namespace of the module being executed. This variable always holds
|
||||
the true module name, even if ``__name__`` is set to something else
|
||||
(like ``'__main__'``)
|
||||
Investigation into why implicit relative imports *appear* to work when
|
||||
a main module is executed directly but fail when executed using -m
|
||||
showed that such imports are actually always treated as absolute
|
||||
imports. Because of the way direct execution works, the package
|
||||
containing the executed module is added to sys.path, so its sibling
|
||||
modules are actually imported as top level modules. This can easily
|
||||
lead to multiple copies of the sibling modules in the application if
|
||||
implicit relative imports are used in modules that may be directly
|
||||
executed (e.g. test modules or utility scripts).
|
||||
|
||||
Modules that don't rely on relative imports can be used from a
|
||||
package as a main module without any changes. In order to both use
|
||||
relative imports and also be usable as a main module, a module in a
|
||||
package will currently need to use a structure similar to the
|
||||
following::
|
||||
For the 2.5 release, the recommendation is to always use absolute
|
||||
imports in any module that is intended to be used as a main module.
|
||||
The -m switch provides a benefit here, as it inserts the current
|
||||
directory into sys.path, instead of the directory contain the main
|
||||
module. This means that it is possible to run a module from inside a
|
||||
package using -m so long as the current directory contains the top
|
||||
level directory for the package. Absolute imports will work correctly
|
||||
even if the package isn't installed anywhere else on sys.path. If the
|
||||
module is executed directly and uses absolute imports to retrieve its
|
||||
sibling modules, then the top level package directory needs to be
|
||||
installed somewhere on sys.path (since the current directory won't be
|
||||
added automatically).
|
||||
|
||||
# Docstring and any future statements
|
||||
_is_main = False
|
||||
if __name__ == "__main__":
|
||||
_is_main = True
|
||||
__name__ = __module_name__
|
||||
Here's an example file layout::
|
||||
|
||||
# Support module section, including relative imports
|
||||
devel/
|
||||
pkg/
|
||||
__init__.py
|
||||
moduleA.py
|
||||
moduleB.py
|
||||
test/
|
||||
__init__.py
|
||||
test_A.py
|
||||
test_B.py
|
||||
|
||||
if _is_main:
|
||||
# Main module section
|
||||
So long as the current directory is ``devel``, or ``devel`` is already
|
||||
on ``sys.path`` and the test modules use absolute imports (such as
|
||||
``import pkg moduleA`` to retrieve the module under test, PEP 338
|
||||
allows the tests to be run as::
|
||||
|
||||
That said, Guido's recommended solution is to avoid using relative
|
||||
imports in the first place.
|
||||
python -m pkg.test.test_A
|
||||
python -m pkg.test.test_B
|
||||
|
||||
The question of whether or not relative imports should be supported
|
||||
when a main module is executed with -m is something that will be
|
||||
revisited for Python 2.6. Permitting it would require changes to
|
||||
either Python's import semantics or the semantics used to indicate
|
||||
when a module is the main module, so it is not a decision to be made
|
||||
hastily.
|
||||
|
||||
Resolved Issues
|
||||
================
|
||||
|
|
Loading…
Reference in New Issue