已经使用了平面软件包,我没想到嵌套软件包会遇到这个问题。这是…
目录布局
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不希望这样:失败,并显示消息:“没有名为模块的模块”。但是……
# 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既可以处理子包,也可以处理子包,但是不需要处理全局配置就可以处理本地内容。 - 我还尝试在中使用import
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.