Python:导入子包或子模块

Hibou57:

已经使用了平面软件包,我没想到嵌套软件包会遇到这个问题。这是…

目录布局

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 '...'>所以这是一个模块,但不是一个模块/ -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.
布伦·巴恩:

您似乎误会了如何import搜索模块。当您使用import语句时,它始终会搜索实际的模块路径(和/或sys.modules)。它不使用由于先前的导入而存在的本地名称空间中的模块对象当您这样做时:

import package.subpackage.module
from package.subpackage import module
from module import attribute1

第二行查找名为的程序包,package.subpackagemodule从该程序包中导入该行对第三行无效。第三行仅查找一个名为的模块module,但未找到一个模块它不会“重复使用” module您从上一行获得的对象

换句话说,from someModule import ...这并不意味着“来自我之前导入的名为someModule的模块...”,它的意思是“来自您在sys.path上找到的名为someModule的模块...”。没有办法通过导入引导模块的软件包来“增量地”构建模块的路径。导入时,您始终必须引用整个模块名称。

目前尚不清楚您要实现的目标。如果您只想导入特定的对象attribute1,则只需from package.subpackage.module import attribute1对其进行操作即可。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

如果您不喜欢输入package.subpackage两次,则可以手动创建对attribute1的本地引用:

from package.subpackage import module
attribute1 = module.attribute1
attribute1 # works
module.someOtherAttribute #also works

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章