[Python-Dev] Relative imports in Py3k (original) (raw)

Nick Coghlan ncoghlan at gmail.com
Sun Sep 26 13:32:47 CEST 2010


On Sat, Sep 25, 2010 at 11:15 PM, anatoly techtonik <techtonik at gmail.com> wrote:

Hi,

I wonder if situation with relative imports in packages is improved in Python 3k or we are still doomed to a chain of hacks? My user story: I am currently debugging project, which consists of many modules in one package. Each module has tests or other useful stuff for debug in its main section, but it is a disaster to use it, because I can't just execute the module file and expect it to find relatives. All imports are like: from spyderlib.config import geticon from spyderlib.utils.qthelpers import translate, addactions, createaction

This is almost certainly failing because the directory containing the spyderlib package isn't on sys.path anywhere (instead, whichever directory contains the script you executed directly will be in there, which will be somewhere inside the package instead of outside it). Put the appropriate directory in PYTHONPATH and these tests should start working.

PEP 328 http://www.python.org/dev/peps/pep-0328/  proposes:

from ... import config from ..utils.qthelpers import translate, addactions, createaction

This fails for two reasons:

  1. "main" is missing the module namespace information PEP 328 needs to do its thing
  2. Even if 1 is resolved, PEP 328 will resolve to the same absolute imports you're already using and likely fail for the same reason (i.e. spyderlib not found on sys.path)

But this doesn't work, and I couldn't find any short user level explanation why it is not possible to make this work at least in Py3k without additional magic.

If you use the -m switch to run your module from the directory that contains the spyderlib package directory, it will work. The use of -m provides the module namespace information that PEP 328 needs, while running from the directory that contains the spyderlib package ensures it is visible through sys.path.

The one caveat is that the specified module is run as "main" and hence does not exist in sys.modules under its normal name. If it gets imported by another module, then you will end up with two copies of the module (one as "main" and one under the normal name). This may or may not cause problems, depending on the nature of the module being executed.

While PEP 366 describes the boilerplate you can put at the top of your module to allow a directly executed module to try to find its siblings, it still requires that PYTHONPATH be set appropriately. And if you set PYTHONPATH appropriately, then direct execution with absolute imports will work.

(The explanation of the failures applies for all Python versions that I am aware of, but the -m based fix only became available in 2.6) (The impact of various command line options and the PYTHONPATH environment variable on sys.path are described at http://docs.python.org/using/cmdline.html) (The basic import search algorithm is described in the tutorial: http://docs.python.org/tutorial/modules.html#the-module-search-path) (And the full gory specification details are in PEP 302, with a few subsequent tweaks courtesy of PEP 328 and PEP 366).

Cheers, Nick.

-- Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-Dev mailing list