Issue 19211: from relative_module import seems to import wrong module (original) (raw)
I have a library lib. lib/init.py does the following:
from .subdir import a
from . import a
import sys
print(sys.modules['lib.a'])
This code fails with a KeyError. It seems that despite the second line, lib.a does not get imported. Printing a.name shows lib.subdir.a. Commenting out the first line makes the code work fine, as does moving the code from lib/init.py to lib/api.py. This happens under both Python 2.7 and Python 3.3.
Here is my sys.path, sys.meta_path, and sys.path_hooks under Python 2.7:
(['/home/ethan/tmp/import-madness', '/home/ethan/tmp/software/notmuch/bindings/python', '/home/ethan/local/lib/python2.7/site-packages', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/ethan/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7'], [], [<type 'zipimport.zipimporter'>])
The same under Python 3:
['/home/ethan/tmp/import-madness', '/home/ethan/local/lib/python2.7/site-packages', '/usr/lib/python3.3', '/usr/lib/python3.3/plat-x86_64-linux-gnu', '/usr/lib/python3.3/lib-dynload', '/usr/local/lib/python3.3/dist-packages', '/usr/lib/python3/dist-packages'] [<class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib.PathFinder'>] [<class 'zipimport.zipimporter'>, <function FileFinder.path_hook..path_hook_for_FileFinder at 0x7f0728babdd0>]
I believe that this is because once you execute the first line, 'a' exists as a name in the 'lib' namespace, so 'from . import a' sees that 'a' already exists, and does nothing. The same import sequence in abc.py will put 'a' into the 'abc' namespace, but 'from . import a' will be looking in the 'lib' namespace, won't see an 'a', and will do the new import, overwriting the definition of 'a' in the 'abc' namespace as it does so.
The exact effects of imports inside init is sometimes a bit non-intuitive.