This appeared in the context of answering another question today.
Suppose the following files, where comments indicate file names:
# level1/__init__.py import level1.level2 answer = level1.level2.answer
With this code, python -c "import level1" works fine (both in 2.7 and 3.4) as it is. But change the answer to anything but 42, and it's not with AttributeError: 'module' object has no attribute 'level2' in the specified location.
It seems that from / import it can import the package submodule and push the variables out of its namespace before all the parent namespaces are created, but (obviously) the parent namespaces must be configured before the sub-namespace attributes can go through regular calls to attributes.
Sometimes, however, the namespace is set up "good enough" for import to work. For example, the code below with the top level disabled always works with python -c "import level2" , although we have not finished initializing the level2 namespace when we import level2.a from level2.b .
# level2/__init__.py from .b import answer
EDIT
It appears that import xyz inserts a link to z in y, but will not insert a link to y in x. For example, when I change level1/level2/b.py from my first example:
# level1/level2/b.py from sys import modules def dump(): print '\n Dumping...' for key, value in sorted(modules.items()): if key.startswith('level'): print key, [ x for x in dir(value) if not x.startswith('_')] dump() import level1.level2.a dump() from .a import answer from ..level2.a import answer from level1.level2.a import answer if answer != 42: answer = level1.level2.a.answer
I get the following results before tracing:
Dumping... level1 [] level1.level2 [] level1.level2.b ['dump', 'modules'] level1.level2.sys [] Dumping... level1 [] level1.level2 ['a'] level1.level2.a ['answer'] level1.level2.b ['dump', 'level1', 'modules'] level1.level2.level1 [] level1.level2.sys []
However, if immediately after the second call to dump() I add the line:
setattr(modules['level1'], 'level2', modules['level1.level2'])
then this will not work, because I linked level2 to level1 before accessing it through an attribute search. However, it seems that if the interpreter can bind a in level1 to this import, it can also bind level2 to level exactly the same way.
Is there a good reason why only the lowest-level package is updated during the import operation, or is it an error (or, rather, a function that was added for a single package that needs to be expanded to nested packages)?
NOTE According to Python documentation. When a submodule is loaded using any mechanism ... the binding is placed in the namespace parent modules for the submodule object. .
I believe this is happening. But not so soon in all cases. In addition, the documentation for it may be relatively new .