当前位置: 首页 > 面试题库 >

Python:导入子包或子模块

宗政卓
2023-03-14
问题内容

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

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的包和子包模型确实发生了问题。

html" target="_blank">笔记

  • 我不想依赖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


 类似资料:
  • 我有一个这样的目录: 我可以这样导入父模块: 那么,既然我已经有了父模块,那么获取子模块的最佳方法是什么?我已经尝试了,,等。 有什么建议吗? 谢谢

  • 问题内容: 我正在学习Python,但无法弄清楚导入的工作方式。 我从Python教程中了解到该文件初始化了一个程序包,并且可以在此处导入子程序包。 不过,我做错了。您能为我(以及将来的Python学习者)解释我做错了什么吗? 这是我正在尝试做的一个简化示例。 这是我的文件结构: 内容: 是空的。 包含: 最后,包含: 这就是我尝试使用OSX终端和Python 3运行hello_world.py的

  • (我意识到在与python相对导入相关的StackOverflow上有很多问题;我也怀疑我做得完全错误;但不管怎样,还是这样吧……) 我有一个python项目(mysubmod)组织如下: 重要的是: /models/hello.py导入lib.foobar 然后我有了第二个项目(myproj),我将mysubmod作为git子模块导入其中;myproj现在组织如下- 哪里: scripts/te

  • 我有一个使用git子模块的项目。在我的python文件中,我想在子模块项目中使用另一个python文件中的函数。 为了工作,我必须将init.py文件添加到路径中的所有子文件夹中。我的文件夹树如下: 有没有办法让它在不接触mygitsubmodule的情况下工作? 谢谢

  • 我在Pycharm中有一个python项目,其中有一个嵌套的Git子模块。以下是文件夹结构: 中的导入结构如下: 但是,Pycharm没有意识到这一点,而是希望我拥有以下内容: 这是有问题的,因为我不想更改中的所有导入(这似乎不是一个好的实践,也不可扩展),而且中有破折号,这对于导入来说不是有效的Python语法(我无法重命名repo)。 我还需要一种从我的代码中导入的方法。像这样的东西: 但当然

  • 问题内容: 我似乎无法获得鼻子测试框架来识别文件结构中测试脚本下的模块。我设置了最简单的示例来演示该问题。我会在下面解释。 这是包文件的结构: foo.py包含: tests / test_foo.py包含: 两个 init .py文件均为空 如果我在主目录(foo.py所在的目录)中运行,则会得到: 当我从tests /目录中运行时,出现相同的错误。根据文档和我发现的示例,nose应该将所有父包