由于我已经使用了平面包,所以我没有预料到我在嵌套包中遇到的问题。以下是…
目录结构
dir
|
+-- test.py
|
+-- package
|
+-- __init__.py
|
+-- subpackage
|
+-- __init__.py
|
+-- module.py
init.py文件的内容
package/__init__.py
和package/subpackage/__init__.py
都是空的。
module.py
文件的内容
# file `package/subpackage/module.py`
attribute1 = "value 1"
attribute2 = "value 2"
attribute3 = "value 3"
# and as many more as you want...
test.py
文件内容(3个版本)
版本1
# file test.py
from package.subpackage.module import *
print attribute1 # OK
那是一种不好且不安全的导入方式(批量导入所有内容),但它确实有效。
版本 2
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1
一种更安全的逐个导入模块的方法,但它失败了,Python不想要这样:它会报错 "No module named module"。然而...
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here
...显示<module 'package.subpackage.module' from '...'>
。那是一个模块,但不是一个模块/-P 8-O ... 呃
版本3
# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK
这一个可用。所以你要么被迫一直使用过度的前缀,要么使用不安全的方式(如版本#1中禁止使用的方式),但 Python 不允许使用方便且安全的方式?更好的方法是安全的,避免了不必要的长前缀,但 Python 拒绝了这种方法?这是因为它喜欢import *
还是因为它喜欢过长的前缀(这并没有帮助强制执行这个惯例)?抱歉用了一些刻薄的话,但我已经尝试两天来解决这种愚蠢的行为。除非我完全错了,否则这会让我感到Python的包和子包模型真的出了问题。
注:
- 我不想依赖于
sys.path
,以避免全局副作用,也不想依赖于*.pth
文件,这只是另一种使用相同全局效果的sys.path
的方法。为了使解决方案干净,它必须是本地的。Python 要么能够处理子包,要么不能,但它不应该需要在全局配置上进行操作才能处理本地东西。
- 我也尝试在package/subpackage/__init__.py
中使用导入,但这解决不了问题,它做了同样的事情,并抱怨subpackage
不是已知模块,而print subpackage
则表明它是一个模块(又是奇怪的行为)。除了我尝试过的三种方法之外,还有其他已知的方法吗?还有我不知道的东西吗?
(叹气)
结论(在人们的评论之后):
在 Python 中没有真正的子包,因为所有包引用都指向全局字典,这意味着没有本地字典,这意味着没有办法管理本地包引用。
您必须使用完整前缀、短前缀或别名。例如:
from package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)
短前缀版本(但是有重复的前缀)
from package.subpackage import module
# Short but then you have to do:
use_of (module.attribute1)
# and repeat the prefix at every use place
否则,以上内容的一个变体。from package.subpackage import module as m
use_of (m.attribute1)
# `m` is a shorter prefix, but you could as well
# define a more meaningful name after the context
分解版本
如果您不介意一次批量导入多个实体,可以采取以下方法:
from package.subpackage.module import attribute1, attribute2
# and etc.
这并不是我最喜欢的方式(我更喜欢每个导入实体都有一个import语句),但可能是我个人喜欢的方式。
更新(2012-09-14):
实践中似乎没什么问题,只是布局需要注意。我使用了以下方式代替以上方式:
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.
__all__
变量,其中包含应在星号导入时导出的名称列表。 编辑:好的,看了BrenBarn的回答,我明白你的意思了。 - Bakuriu