[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