Python:导入一个子包或子模块

已经使用扁平软件包,我不期待我遇到的嵌套软件包的问题。 这是…

目录布局

dir | +-- test.py | +-- package | +-- __init__.py | +-- subpackage | +-- __init__.py | +-- module.py 

init .py的内容

package/__init__.pypackage/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. 

你似乎误解了如何importsearch模块。 当你使用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