清理Python中的包导入
我有一个这样的项目结构:
project
|----app.py
|----package
|---__init__.py
|---module.py
|---module2.py
|---module3.py
|---....
我的 __init__.py
文件现在是空的。在 module.py 里,我定义了一个类:
class UsefulClass:
...
在其他模块里也有类似的定义。我的 app.py 看起来是这样的:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from package.module import UsefulClass
from package.module2 import UsefulClass2
...
usefulclass = UsefulClass()
usefulclass2 = UsefulClass2()
....
我的问题是:我该如何替换这些 from package.module... import UsefulClass
的语句?现在我只有4个模块,但这些导入看起来开始有点乱了。我能不能在 __init__.py
文件里导入它们,然后在 app.py
里只用 import package
?我试过这样做,但出现了错误。
我在寻找一个干净优雅的解决方案。
1 个回答
在Python 3中:
package/__init__.py
:
from .foo import bar
package/foo.py
:
bar=0
app1.py
:
import package
print(package.bar)
app2.py:
from package import bar
print(bar)
无论哪种方式,这都会打印出0
,正如你想要的那样。
在Python 2中,只需将from .foo import bar
改为from foo import bar
。
(实际上,2.x的代码在Python 3中通常也能运行,但这并不正确,在某些特殊情况下会失败。例如,如果你在应用程序同级目录下有一个bar.py
,那么你得到的bar
将是那个模块,而不是0
。)
在实际使用中,你可能想要为每个包和模块指定一个__all__
,这样你就可以使用from foo import …
(至少这样可以在交互式解释器中用from foo import *
来测试东西)。
听起来你是说你已经尝试过这个,并且遇到了错误。没有确切知道你尝试了什么,错误是什么,以及你使用的是哪个Python版本,我无法判断你可能哪里出错了,但可以推测你肯定是出错了。
.foo
表示相对导入。说from .foo import bar
的意思是“从和我在同一个包里的foo
模块中导入bar
”。如果你去掉点号,就是在说“从标准模块路径中的foo
模块导入bar
”。
关于包内引用的教程部分在这里有简要说明。关于import
的参考文档和导入系统的一般信息提供了大部分细节,但最初的提案在PEP 328中更简单地解释了细节和设计背后的原因。
在2.x中需要去掉点号的原因是,2.x没有办法区分相对导入和绝对导入。只有from foo import bar
,这意味着“从和我在同一个包里的foo
模块中导入bar
,或者如果没有这样的模块,就从标准模块路径中导入bar
”。