[Python-ideas] Packages and Import

Brett Cannon brett at python.org
Sun Feb 11 21:03:21 CET 2007


On 2/11/07, Josiah Carlson <jcarlson at uci.edu> wrote:
>
> "Brett Cannon" <brett at python.org> wrote:
> >
> > On 2/11/07, Josiah Carlson <jcarlson at uci.edu> wrote:
> > >
> > > Josiah Carlson <jcarlson at uci.edu> wrote:
> > > > 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.
> > >
> > > And in that vein, I have implemented a bit of code that mangles the
> > > __name__ of the __main__ module, sets up pseudo-packages for parent
> > > paths with valid Python names, imports __init__.py modules in ancestor
> > > packages, adds an ismain() function to builtins, etc.
> > >
> > > It allows for crazy things like...
> > >
> > >     from ..uncle import cousin
> > >     from ..parent import sibling
> > >     #the above equivalent to:
> > >     from . import sibling
> > >     from .sibling import nephew
> > >
> > > ...all executed within the __main__ module (which gets a new __name__).
> > > Even better, it works with vanilla Python 2.5, and doesn't even require
> > > an import hook.
> > >
> > > The only unfortunate thing is that because you cannot predict how far up
> > > the tree relative imports go, you cannot know how far up the paths one
> > > should go in creating the ancestral packages.  My current (simple)
> > > implementation goes as far up as the root, or the parent of the deepest
> > > path with an __init__.py[cw] .
> > >
> >
> > Just to make sure that I understand this correctly, __name__ is set to
> > __main__ for the module that is being executed.  Then other modules in
> > the package are also called __main__, but with the proper dots and
> > such to resolve to the proper depth in the package?
>
> No.  Say, for example, that you had a tree like the following.
>
>     .../
>         pk1/
>             pk2/
>                 __init__.py
>                 pk3/
>                     __init__.py
>                     run.py
>
> Also say that run.py was run from the command line, and the relative
> import code that I have written gets executed.  The following assumes
> that at least a "dummy" module is inserted into sys.modules['__main__']
>
> 1) A fake package called 'pk1' with __path__ == ['../pk1'] is inserted
> into sys.modules.
> 2) 'pk1.pk2' is imported as per package rules (__init__.py is executed),
> and gets a __path__ == ['../pk1/pk2/'] .
> 3) 'pk1.pk2.pk3' is imported as per package rules (__init__.py is
> executed), and gets a __path__ == ['../pk1/pk2/pk3'] .
> 4) We fetch sys.packages['__main__'], give it a new __name__ of
> 'pk1.pk2.pk3.__main__', but don't give it a path.  Also insert the
> module into sys.modules['pk1.pk2.pk3.__main__'].
> 5) Add ismain() to builtins.
> 6) The remainder of run.py is executed.
>

Ah, OK.  Didn't realize you had gone ahead and done step 5.

>
> > > If you are curious, I can send you a copy off-list.
> >
> > I have way too much on my plate right now to dive into it right now,
> > but I assume the patch is either against runpy or my import code?
>
> No.  It's actually a standalone module.  When imported (presumably from
> __main__ as the first thing it does), it performs the mangling,
> importing, etc.  I'm sure I could modify runpy to do all of this, but
> only if alter_sys was True.
>
> I could probably do the same with your import code, where can I find it?
>

It's in the sandbox under import_in_py if you want the Python version.

-Brett



More information about the Python-ideas mailing list