146 lines
5.6 KiB
Plaintext
146 lines
5.6 KiB
Plaintext
PEP: 366
|
|
Title: Main module explicit relative imports
|
|
Version: $Revision$
|
|
Last-Modified: $Date$
|
|
Author: Nick Coghlan <ncoghlan@gmail.com>
|
|
Status: Final
|
|
Type: Standards Track
|
|
Content-Type: text/x-rst
|
|
Created: 01-May-2007
|
|
Python-Version: 2.6, 3.0
|
|
Post-History: 01-May-2007, 04-Jul-2007, 07-Jul-2007, 23-Nov-2007
|
|
|
|
|
|
Abstract
|
|
========
|
|
|
|
This PEP proposes a backwards compatible mechanism that permits
|
|
the use of explicit relative imports from executable modules within
|
|
packages. Such imports currently fail due to an awkward interaction
|
|
between :pep:`328` and :pep:`338`.
|
|
|
|
By adding a new module level attribute, this PEP allows relative imports
|
|
to work automatically if the module is executed using the ``-m`` switch.
|
|
A small amount of boilerplate in the module itself will allow the relative
|
|
imports to work when the file is executed by name.
|
|
|
|
Guido accepted the PEP in November 2007 [5]_.
|
|
|
|
Proposed Change
|
|
===============
|
|
|
|
The major proposed change is the introduction of a new module level
|
|
attribute, ``__package__``. When it is present, relative imports will
|
|
be based on this attribute rather than the module ``__name__``
|
|
attribute.
|
|
|
|
As with the current ``__name__`` attribute, setting ``__package__`` will
|
|
be the responsibility of the :pep:`302` loader used to import a module.
|
|
Loaders which use ``imp.new_module()`` to create the module object will
|
|
have the new attribute set automatically to ``None``. When the import
|
|
system encounters an explicit relative import in a module without
|
|
``__package__`` set (or with it set to ``None``), it will calculate and
|
|
store the correct value (``__name__.rpartition('.')[0]`` for normal
|
|
modules and ``__name__`` for package initialisation modules). If
|
|
``__package__`` has already been set then the import system will use
|
|
it in preference to recalculating the package name from the
|
|
``__name__`` and ``__path__`` attributes.
|
|
|
|
The ``runpy`` module will explicitly set the new attribute, basing it off
|
|
the name used to locate the module to be executed rather than the name
|
|
used to set the module's ``__name__`` attribute. This will allow relative
|
|
imports to work correctly from main modules executed with the ``-m``
|
|
switch.
|
|
|
|
When the main module is specified by its filename, then the
|
|
``__package__`` attribute will be set to ``None``. To allow
|
|
relative imports when the module is executed directly, boilerplate
|
|
similar to the following would be needed before the first relative
|
|
import statement::
|
|
|
|
if __name__ == "__main__" and __package__ is None:
|
|
__package__ = "expected.package.name"
|
|
|
|
Note that this boilerplate is sufficient only if the top level package
|
|
is already accessible via ``sys.path``. Additional code that manipulates
|
|
``sys.path`` would be needed in order for direct execution to work
|
|
without the top level package already being importable.
|
|
|
|
This approach also has the same disadvantage as the use of absolute
|
|
imports of sibling modules - if the script is moved to a different
|
|
package or subpackage, the boilerplate will need to be updated
|
|
manually. It has the advantage that this change need only be made
|
|
once per file, regardless of the number of relative imports.
|
|
|
|
Note that setting ``__package__`` to the empty string explicitly is
|
|
permitted, and has the effect of disabling all relative imports from
|
|
that module (since the import machinery will consider it to be a
|
|
top level module in that case). This means that tools like ``runpy``
|
|
do not need to provide special case handling for top level modules
|
|
when setting ``__package__``.
|
|
|
|
Rationale for Change
|
|
====================
|
|
|
|
The current inability to use explicit relative imports from the main
|
|
module is the subject of at least one open SF bug report (#1510172) [1]_,
|
|
and has most likely been a factor in at least a few queries on
|
|
comp.lang.python (such as Alan Isaac's question in [2]_).
|
|
|
|
This PEP is intended to provide a solution which permits explicit
|
|
relative imports from main modules, without incurring any significant
|
|
costs during interpreter startup or normal module import.
|
|
|
|
The section in :pep:`338` on relative imports and the main module provides
|
|
further details and background on this problem.
|
|
|
|
|
|
Reference Implementation
|
|
========================
|
|
|
|
Rev 47142 in SVN implemented an early variant of this proposal
|
|
which stored the main module's real module name in the
|
|
``__module_name__`` attribute. It was reverted due to the fact
|
|
that 2.5 was already in beta by that time.
|
|
|
|
Patch 1487 [4]_ is the proposed implementation for this PEP.
|
|
|
|
Alternative Proposals
|
|
=====================
|
|
|
|
:pep:`3122` proposed addressing this problem by changing the way
|
|
the main module is identified. That's a significant compatibility cost
|
|
to incur to fix something that is a pretty minor bug in the overall
|
|
scheme of things, and the PEP was rejected [3]_.
|
|
|
|
The advantage of the proposal in this PEP is that its only impact on
|
|
normal code is the small amount of time needed to set the extra
|
|
attribute when importing a module. Relative imports themselves should
|
|
be sped up fractionally, as the package name is cached in the module
|
|
globals, rather than having to be worked out again for each relative
|
|
import.
|
|
|
|
|
|
References
|
|
==========
|
|
|
|
.. [1] Absolute/relative import not working?
|
|
(https://github.com/python/cpython/issues/43535)
|
|
|
|
.. [2] c.l.p. question about modules and relative imports
|
|
(http://groups.google.com/group/comp.lang.python/browse_thread/thread/c44c769a72ca69fa/)
|
|
|
|
.. [3] Guido's rejection of PEP 3122
|
|
(https://mail.python.org/pipermail/python-3000/2007-April/006793.html)
|
|
|
|
.. [4] PEP 366 implementation patch
|
|
(https://github.com/python/cpython/issues/45828)
|
|
|
|
.. [5] Acceptance of the PEP
|
|
(https://mail.python.org/pipermail/python-dev/2007-November/075475.html)
|
|
|
|
Copyright
|
|
=========
|
|
|
|
This document has been placed in the public domain.
|