Updated writeup about import statements to strongly recommend absolute imports from main modules

This commit is contained in:
Nick Coghlan 2006-07-06 12:36:24 +00:00
parent a218af0b7f
commit 09618837a9
1 changed files with 54 additions and 26 deletions

View File

@ -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
================