[Python-ideas] Packages and Import

Josiah Carlson jcarlson at uci.edu
Sun Feb 11 01:42:57 CET 2007


"Brett Cannon" <brett at python.org> wrote:
> On 2/9/07, Josiah Carlson <jcarlson at uci.edu> wrote:
> >
> > "Brett Cannon" <brett at python.org> wrote:
> > > On 2/9/07, Josiah Carlson <jcarlson at uci.edu> wrote:
[snip]
> > How is it done now?
> 
> Importers and loaders; see PEP 302.

Wow, I should have started there when I was doing my relative import
work.  That's much nicer to work with.

[snip]

> > > > It also naturally leads to a __name__ semantic that Guido had suggested
> > > > to me when I was talking about relative imports:
> > > >
> > > >     goo.__name__ == '__main__'
> > > >     foo.__name__ == '__main__.foo'
> > > >     baz.__name__ == '__main__..bar.baz'
> > > >
> > > > Which could more or less be used with the current importer; it just
> > > > needs a special-casing of 'from . import ...' in the __main__ module.
> > >
> > > And I am trying to avoid special-casing for this.
> >
> > And it's only really an issue because we can't currently discern between
> > module or package, right?
> 
> Basically.  It's also where within a package the module is, so it
> isn't quite that simple.
> 
> The issue comes down to that we lose where a module is contained
> within a package hierarchy once __name__ gets set to __main__.  If we
> came up with another way to delineate that a module was being executed
> or some other way to specify where a module was in a package then the
> problem would be solved.  I prefer trying to change the former since
> the latter is perfectly handled with __name__ as-is when it isn't
> changed to __main__.

Kind-of.  It still seems to break in a few cases, which I believe to be
the result of current __name__ semantics (which can be fixed if __name__
could be anything, but I'll talk about that again later).

Say I wanted to do relative imports in paths below the current __main__
module.  The following works, and gives me the __main__-derived package
names that Guido suggested.

    >>> __path__ = [os.getcwd()]
    >>> from . import bar
    >>> bar
    <module '__main__.bar' from 'D:\Projects\python\py25\bar.pyc'>

So far so good.  What about "cousin" relative imports (an issue I've had
to deal with myself)?

    >>> from ..py25b import baz
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: Relative importpath too deep

No dice.  Sub-packages seem to be ok with this hack to __main__, but
nothing that goes to a parent of the "root" package of __main__.

My attempts to hack __main__ with...

    __name__ = '.'.join(os.getcwd().split('\\')[1:])

just got me "parent package not loaded".  Adding fake parent packages
all the way to the root of the drive, leaving the above name mangling in
place, allowed me to do the 'from ..py25b import baz' import in the
"main" module.


I like Guido's suggestion; allow multiple trailing dots off of
__main__.  That is, suppose that we were able to do the "from ..py25b
import baz" import, the __name__ of the imported object should be
__main__..py25b.baz .  Allowing that particular semantic would let us
keep the "if __name__ == '__main__':" thing we've been doing.  This,
however, would require a bunch of extra coding.


Anyways...I hear where you are coming from with your statements of 'if
__name__ could be anything, and we could train people to use ismain(),
then all of this relative import stuff could *just work*'.  It would
require inserting a bunch of (fake?) packages in valid Python name
parent paths (just in case people want to do cousin, etc., imports from
__main__).

You have convinced me.

 - Josiah




More information about the Python-ideas mailing list