# [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:])

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