You incorrectly assume that one cannot have an alias with from ... import
, as from ... import ... as
has been there since Python 2.0. The import ... as
is the obscure syntax that not many know about, but which you use by accident in your code.
PEP 0221 claims that the following 2 are “effectively” the same:
import foo.bar.bazaar as baz
from foo.bar import bazaar as baz
The statement is not quite true in Python versions up to and including 3.6.x as evidenced by the corner case you met, namely if the required modules already exist in sys.modules
but are yet uninitialized. The import ... as
requires that the module foo.bar
is injected in foo
namespace as the attribute bar
, in addition to being in sys.modules
, whereas the from ... import ... as
looks for foo.bar
in sys.modules
.
(Do note also that import foo.bar
only ensures that the module foo.bar
is in sys.modules
and accessible as foo.bar
, but might not be fully initialized yet.)
Changing the code as follows did the trick for me:
# import pkg.subpkg.two_longname as two
from pkg.subpkg import two_longname as two
And code runs perfectly on both Python 2 and Python 3.
Also, in one.py
you cannot do from pkg import subpkg
, for the same reason.
To demonstrate this bug further, fix your one.py
as above, and add the following code in tst.py
:
import pkg
import pkg.subpkg.two_longname as two
del pkg.subpkg
from pkg.subpkg import two_longname as two
import pkg.subpkg.two_longname as two
Only the last line crashes, because from ... import
consults the sys.modules
for pkg.subpkg
and finds it there, whereas import ... as
consults sys.modules
for pkg
and tries to find subpkg
as an attribute in the pkg
module. As we just had deleted that attribute, the last line fails with AttributeError: 'module' object has no attribute 'subpkg'
.
As the import foo.bar as baz
syntax is a bit obscure and adds more corner cases, and I have rarely if ever seen it being used, I would recommend avoiding it completely and favouring from .. import ... as
.