[Python-ideas] Allow 'import star' with namespaces

Eric Snow ericsnowcurrently at gmail.com
Mon May 9 20:55:20 CEST 2011


On Mon, May 9, 2011 at 8:04 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:

> On Sat, May 7, 2011 at 6:52 AM, Eric Snow <ericsnowcurrently at gmail.com>
> wrote:
>
> > If you have a list of the submodules you want imported then you can
> already
> > accomplish this:
> > import parent
> > for mod in parent.__all_submodules__:
> >     __import__("parent.{}".format(mod))
>
> > Of course, this does not bind the submodules to the namespace of the
> package
> > module
>
> It actually does, as binding the submodule name in the parent package
> namespace is part of the responsibility of __import__():
>
> >>> import logging
> >>> logging.handlers
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> AttributeError: 'module' object has no attribute 'handlers'
> >>> __import__("logging.handlers")
> <module 'logging' from '/usr/lib/python2.7/logging/__init__.pyc'>
> >>> logging.handlers
> <module 'logging.handlers' from '/usr/lib/python2.7/logging/handlers.pyc'>
>
>
Well, dang it.  Not sure how I missed this before:

$ python3
>>> import temp
>>> dir(temp)
['__builtins__', '__cached__', '__doc__', '__file__', '__name__',
'__package__', '__path__']

$ python3
>>> import temp.mod
>>> dir(temp)
['__builtins__', '__cached__', '__doc__', '__file__', '__name__',
'__package__', '__path__', 'mod']

So the sub-module name binding mechanism is simply to bind the package
module and then bind the submodules to it.  However, "import temp.mod as
something_else" and "from temp import mod" don't do this, which makes sense.

This is one of the reasons circular imports are such a pain - we
> pre-bind them in sys.modules, and remove them again if the import
> fails, but we don't currently do that in the parent package namespace,
> so circular imports sometimes work and sometime break depending not
> only on which names are accessed but also *how* they're accessed (e.g.
> in a/b/c.py, "import a.b.c" will work, "import a.b.c; c = a.b.c" will
> fail with AttributeError and "from a.b import c" will fail with
> ImportError).
>
> > I am not sure
> > of the specific import mechanism with regards to name binding, but that
> > would seem to be a conflict with the way imported names for submodules
> are
> > bound.
>
> Nope, it's basically the same as what happens automatically when the
> modules are imported normally. Indeed, as near as I can tell, this
> request amounts to asking for syntactic sugar that does something
> roughly along the lines of:
>
> def _subnames(pkg_name, subnames):
>    for subname in subnames:
>        yield ".".join(pkg_name, subname)
>
> def import_all(pkg):
>    try:
>        pkg_all = pkg.__all__
>    except AttributeError:
>        pass
>    else:
>        names = list(_subnames(pkg.__name__, pkg_all))
>        for name in names:
>            mod = importlib.import_module(name)
>            try:
>                mod_all = mod.__all__
>            except AttributeError:
>                pass
>            else:
>                names.extend(_subnames(mod.__name__, mod_all)
>
>
This works as long as __all__ only contains submodule names, right?


> I can see a case being made to provide that as a function in pkgutil
> (or perhaps importlib itself), but I don't see any reason to give it
> dedicated syntax.
>
>
+1

-eric


> Cheers,
> Nick.
>
> --
> Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20110509/167444da/attachment.html>


More information about the Python-ideas mailing list