On Mon, May 9, 2011 at 8:04 AM, Nick Coghlan <ncoghlan@gmail.com> wrote:
On Sat, May 7, 2011 at 6:52 AM, Eric Snow <ericsnowcurrently@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@gmail.com | Brisbane, Australia