【发布时间】:2014-09-08 13:18:41
【问题描述】:
我在 __init__.py 中导入并在包的模块中使用带有绝对导入的 import as 时遇到了问题。
我的项目有一个子包,在其__init__.py 中,我使用from import as 语句将其中一个类从模块“提升”到子包级别。该模块使用绝对导入从该子包中导入其他模块。我收到此错误AttributeError: 'module' object has no attribute 'subpkg'。
示例
结构:
pkg/
├── __init__.py
├── subpkg
│ ├── __init__.py
│ ├── one.py
│ └── two_longname.py
└── tst.py
pkg/init.py 为空。
pkg/subpkg/init.py:
from pkg.subpkg.one import One
pkg/subpkg/one.py:
import pkg.subpkg.two_longname as two
class One(two.Two):
pass
pkg/subpkg/two_longname.py:
class Two:
pass
pkg/tst.py:
from pkg.subpkg import One
print(One)
输出:
$ python3.4 -m pkg.tst
Traceback (most recent call last):
File "/usr/lib/python3.4/runpy.py", line 170, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.4/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/and/dev/test/python/imptest2/pkg/tst.py", line 1, in <module>
from pkg.subpkg import One
File "/home/and/dev/test/python/imptest2/pkg/subpkg/__init__.py", line 1, in <module>
from pkg.subpkg.one import One
File "/home/and/dev/test/python/imptest2/pkg/subpkg/one.py", line 1, in <module>
import pkg.subpkg.two_longname as two
AttributeError: 'module' object has no attribute 'subpkg'
解决方法
有一些变化使它起作用:
-
空
pkg/subpkg/__init__.py并直接从pkg.subpkg.one导入。我不认为这是一个选项,因为 AFAIK 将事情“提升”到包装级别是可以的。这是an article的引用:
在您的
__init__.py中要做的一件常见事情是导入选定的 将类、函数等放入包级别,以便它们可以 方便地从包中导入。 -
在
one.py中将import as更改为from import:from pkg.subpkg import two_longname class One(two_longname.Two): pass这里唯一的缺点是我不能为模块创建一个短别名。我从@begueradj 的回答中得到了这个想法。
也可以在one.py 中使用相对导入来解决问题。但我认为这只是解决方法 #2 的一种变体。
问题
-
有人能解释一下这里到底发生了什么吗?为什么
__init__.py中的导入和import as的使用组合会导致这样的问题? -
有没有更好的解决方法?
原始示例
这是我原来的例子。这不是很现实,但我不会删除它,所以@begueradj 的回答仍然有意义。
pkg/init.py 为空。
pkg/subpkg/init.py:
from pkg.subpkg.one import ONE
pkg/subpkg/one.py:
import pkg.subpkg.two
ONE = pkg.subpkg.two.TWO
pkg/subpkg/two.py:
TWO = 2
pkg/tst.py:
from pkg.subpkg import ONE
输出:
$ python3.4 -m pkg.tst
Traceback (most recent call last):
File "/usr/lib/python3.4/runpy.py", line 170, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.4/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/and/dev/test/python/imptest/pkg/tst.py", line 1, in <module>
from pkg.subpkg import ONE
File "/home/and/dev/test/python/imptest/pkg/subpkg/__init__.py", line 2, in <module>
from pkg.subpkg.one import ONE
File "/home/and/dev/test/python/imptest/pkg/subpkg/one.py", line 6, in <module>
ONE = pkg.subpkg.two.TWO
AttributeError: 'module' object has no attribute 'subpkg'
最初我在 one.py 中有这个:
import pkg.subpkg.two as two
ONE = two.TWO
在这种情况下,我在导入时遇到错误(就像在我的原始项目中也使用 import as)。
【问题讨论】:
-
我再次阅读了您的代码,逐个案例。我发现你错过了一个真实的事实:tst.py 位于 pkg 本身之下,所以每次你从任何你想要的地方调用
import pkg.subpkg.SOMETHING或from pkg.subpkg import SOMETHING时,你都会得到同样的错误。我重新编辑了我的答案:我只更改了您程序的结构,主要是 tst.py 在 pkg 之外(实际上,自从我第一次发布以来,我就这样运行它我的回答如下)。如果您想将 tst.py 保留在 pkg 中,请从您的所有呼叫中删除pgk,例如import pkg.subpkg.SOMETHING和from pkg.subpkg import SOMETHING -
tst.py在包里面,就是这样。 “删除pkg你所有的电话......”是什么意思?相对进口?我知道它适用于相对进口。问题是为什么它不能像现在这样工作。 -
我的意思是你需要运行
import subpkg.SOMETHING而不是import pkg.subpkg.SOMETHING和from subpkg import SOMETHING而不是from pkg.subpkg import SOMETHING。为什么 ?好吧:你不能用无效的路径运行你的程序。就这么简单。
标签: python python-3.x python-import