2

This is probably really simple, but I don't understand it. The following works:

foo.py

class Foo:
    pass

bar.py

module = __import__('foo')
foo = module.__dict__['Foo']

Afterwards, foo is the class foo.Foo as expected.


Yet, if I put a.py into a package, it stops working:

qux/__init__.py

(empty file)

qux/foo.py

class Foo:
    pass

bar.py

module = __import__('qux.foo')
foo = module.__dict__['Foo']

Running python bar.py gives me KeyError: 'Foo', but the module import is still successful.

What's going on, and how do I get it to work?

4 Answers 4

3

If you want to import a submodule, you can do something like this:

package = __import__('qux', fromlist=['foo'])
module = getattr(package, 'foo')

Note that with a fromlist the __import__ returns the most nested name in the first parameter, so you could substitute baz.bar.qux in the __import__ call to access the baz.bar.qux.foo module.

Sign up to request clarification or add additional context in comments.

1 Comment

I'm sure this is very Pythonic and makes perfect sense to many people, but man is this convoluted to me. Thanks a million.
3

__import__ applied to nested module names returns the toplevel module/package - which is qux here. All modules are, however, inserted into sys.modules, so you can simply lookup qux.foo in there.

See the PyDoc on __import__() -it's all described there.

2 Comments

Note that 'import qux.foo' works analogously -- qux ends up in the local namespace, but foo is only accessible as an attribute of qux.
Indeed, it suddenly and mysteriously appeared in the docs now that I look again: "When the name variable is of the form package.module, normally, the top-level package (the name up till the first dot) is returned, not the module named by name. However, when a non-empty fromlist argument is given, the module named by name is returned."
2

You can directly access a module, nested or not, using importlib:

import importlib
module_name="qux.foo"
mod=importlib.import_module(module_name)

See http://docs.python.org/dev/library/importlib.html for more details.

Comments

1

You need to use the fromlist parameter to reference a submodule:

temp = __import__('qux.foo', globals(), locals(), ['Foo'], -1)
foo = temp.Foo

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.