Python:导入一个子包或子模块
已经使用扁平软件包,我不期待我遇到的嵌套软件包的问题。 这是…
目录布局
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 '...'>
说<module 'package.subpackage.module' from '...'>
。 所以这是一个模块,但这不是一个模块/ -P 😯 …呃
版本3
# file test.py v3 from package.subpackage.module import attribute1 print attribute1 # OK
这个工作。 那么你是不是一直被迫使用矫枉过正的前缀,或者使用不安全的方式,如#1版本,Python不允许使用安全的方便方式? 更好的方法,这是安全的,避免不必要的长前缀是唯一一个Python拒绝? 这是因为它喜欢import *
还是因为它喜欢超长的前缀(这不利于执行这种做法)?
不好意思的是,这是两天我试图解决这个愚蠢的行为。 除非我在某个地方完全错了,否则这会让我感觉到,Python的包和子包的模型中有些东西真的被破坏了。
笔记
- 我不想依靠
sys.path
来避免全局性的副作用,也不要依赖*.pth
文件,这是使用相同的全局效果来处理sys.path
另一种方法。 为了解决scheme要清洁,只能是本地的。 要么Python能够处理子包,要么不是,但它不应该要求全局configuration来处理本地的东西。 - 我也尝试在
package/subpackage/__init__.py
,但是它没有解决任何问题,它也是这样做的,并且抱怨subpackage
不是一个已知的模块,而print subpackage
说它是一个模块(又是奇怪的行为)。
可能是我完全错了(我更喜欢这个选项),但是这让我对Python感到很失望。
除了三个我试过的其他已知方法? 我不知道的东西?
(叹)
—–%<—–编辑—–>%—–
目前为止的结论(经过人们的评论)
在Python中没有任何东西像真正的子包,因为所有的包引用都会转到全局的dictionnary,这意味着没有本地的字典,这意味着没有办法pipe理本地的包引用。
您必须使用完整的前缀或短前缀或别名。 如:
完整的前缀版本
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实体有一个import声明),但可能是我个人喜欢的。
更新(2012-09-14):
最后在实践中似乎没有问题,除了有关布局的评论。 而不是以上,我用:
from package.subpackage.module import ( attribute1, attribute2, attribute3, ...) # and etc.
你似乎误解了如何import
search模块。 当你使用import语句时,它总是search实际的模块path(和/或sys.modules
)。 它不会使用由于以前导入而存在的本地名称空间中的模块对象 。 当你这样做时:
import package.subpackage.module from package.subpackage import module from module import attribute1
第二行查找一个名为package.subpackage
并从该包中导入module
。 这条线对第三条线没有影响。 第三行只是寻找一个module
,并没有find一个module
。 它不会“重复使用”从上面的行中获得的称为module
的对象。
换句话说, from someModule import ...
并不意味着“从我之前导入的模块调用someModule …”这意味着“从模块名称someModule,你可以在sys.pathfind…”。 没有办法通过导入导致它的包来“增量地”build立一个模块的path。 导入时,您始终必须引用整个模块名称。
目前还不清楚你想达到什么目的。 如果你只想导入特定的对象属性1,只需from package.subpackage.module import attribute1
中做,然后完成它。 一旦你从它input了你想要的名字,你就不用担心长的package.subpackage.module
。
如果你以后想要访问模块来访问其他名字,那么你可以from package.subpackage import module
进行操作,正如你所看到的,你可以尽可能的使用module.attribute1
等等。
如果你想要两个 —也就是说,如果你希望attribute1
直接访问, 并且你希望module
可以访问的话,那么只需要执行以上两个操作:
from package.subpackage import module from package.subpackage.module import attribute1 attribute1 # works module.someOtherAttribute # also works
如果你不喜欢inputpackage.subpackage
两次,你可以手动创build一个对attribute1的本地引用:
from package.subpackage import module attribute1 = module.attribute1 attribute1 # works module.someOtherAttribute #also works
原因#2失败是因为sys.modules['module']
不存在(导入例程具有自己的作用域,并且看不到module
本地名称),并且没有module
模块或软盘包。 请注意,您可以用逗号分隔多个导入的名称。
from package.subpackage.module import attribute1, attribute2, attribute3
也:
from package.subpackage import module print module.attribute1
如果你所要做的只是在你的全局命名空间中得到attribute1,那么版本3就好了。 为什么它是矫枉过正的前缀?
在版本2中,而不是
from module import attribute1
你可以做
attribute1 = module.attribute1