已经使用了平面包,我没想到会遇到嵌套包的问题。这里是……</p>
目录布局
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 不希望这样:失败并显示消息:“没有名为模块的模块”。不过……</p>
# 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
这个有效。所以你要么被迫一直使用 overkill 前缀,要么使用版本 #1 中的不安全方式,并且 Python 不允许使用安全方便的方式?更好的方法,即安全且避免不必要的长前缀是 Python 唯一拒绝的方法?这是因为它喜欢import *
还是因为它喜欢过长的前缀(这无助于实施这种做法)?
抱歉,我用了两天的时间来解决这种愚蠢的行为。除非我在某个地方完全错了,否则这会让我感觉 Python 的包和子包模型中确实存在某些问题。
笔记
- 我不想依赖
sys.path
, 来避免全局副作用,也不想依赖*.pth
文件,这只是sys.path
使用相同全局效果的另一种方式。为了使解决方案干净,它必须是本地的。要么 Python 能够处理子包,要么不能,但它不应该需要使用全局配置来处理本地内容。 - 我也尝试过在中使用导入
package/subpackage/__init__.py
,但它什么也没解决,它做同样的事情,并且抱怨subpackage
不是一个已知的模块,而print subpackage
说它是一个模块(再次奇怪的行为)。
可能是我完全错了强硬(我更喜欢的选项),但这让我对 Python 感到非常失望。
除了我尝试的三种方法之外,还有其他已知的方法吗?有什么我不知道的?
(叹)
----- %< ----- 编辑 ----- >% -----
到目前为止的结论(经过人们的评论)
在 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.
不是我最喜欢的口味(我更喜欢每个进口实体有一个进口声明),但可能是我个人喜欢的。
更新(2012-09-14):
最终在实践中似乎没问题,除了对布局的评论。而不是上述,我使用:
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.