【问题标题】:python import module from a packagepython 从包中导入模块
【发布时间】:2016-07-30 15:18:33
【问题描述】:

文件夹结构:

<current dir>
   main.py
   packages <dir>
      __init__.py
      mod.py

主py:

import packages
print packages.mod.hello()

mod.py:

def hello():
    return 'hello'

__init__.py:

from packages import mod

如果我运行main.py,则不会出错。但是,如果我将 __init__.py 编辑为 'from packages import *' ,我会收到此错误:AttributeError: 'module' object has no attribute 'mod'

我不是在问如何使 'print' 命令工作。我可以在main.py 中使用其他'import' 语法来使其工作。问题是:我很好奇__init__.py 中的'from packages import mod'。如果我可以做到import mod,那么当我替换为import *,这意味着导入所有内容时,为什么会出现错误?

那么from packages import *__init__.py 中的真正含义是什么?

有人可以帮忙吗?谢谢

【问题讨论】:

    标签: python import packages


    【解决方案1】:

    简答

    那么from packages import *__init__.py 中的真正含义是什么?

    __init__.py 自行导入。

    说明

    您只能导入模块,不能导入包。包只是模块或子包的容器。当你“导入”一个包时,你实际上导入了模块__init__.py

    带有此内容的__init__.py

    from packages import mod
    

    将模块mod 导入__init__.py。因此,它将可用 通过packages.mod 在您的main.py 中(记住packages__init__.py 表示)。

    当你把__init__.py的内容改成:

    from packages import *
    

    您正在导入模块 __init__.py,与您所在的文件完全相同。 这有效(第二次导入只会触发在sys.modules 中的查找) 但不会给你mod的内容。

    这意味着,您可以使用:

    from module import *
    

    但您不能明智地将其与空的 __init__.py 一起使用:

    from package import *
    

    因为package 实际上是由__init__.py 表示的 还没有。你可以检查这个(以交互方式或在文件中):

    >>> import packages
    >>> print(packages)
    <module 'packages' from '/.../packages/__init__.py'>
    

    __init__.py你可以写:

    from packages.mod import *
    

    然后在main.py:

    print packages.hello()
    

    有效。因为函数hello() 现在位于 文件__init__.py

    正如mozman的回答中提到的,您可以在__init__.py中使用__all__ 如果使用了from packages import *,则列出should be imported 的模块。这是为这种情况设计的。

    __init__.py只有这个内容:

    __all__ = ['mod']
    

    现在您可以在main.py 中执行此操作:

    from packages import *
    
    print mod.hello()
    

    如果你扩展你的__init__.py:

    __all__ = ['mod']
    
    from packages import *
    

    您可以在main.py

    import packages
    
    print packages.mod.hello()
    

    但如果你从__init__.py 中删除from packages import *

    __all__ = ['mod'] 
    

    你会得到一个错误:

    AttributeError: 'module' object has no attribute 'mod'
    

    因为__all__ 仅用于from packages import * 情况。 现在我们回到 __init__.py 导入本身。

    【讨论】:

    • 可以from package import * 因为编译时不会出错,只有当我打印时它才说没有模块'mod'。所以该命令是有效的,只是我对代码在做什么感到困惑。
    【解决方案2】:

    另请参阅:In Python, what exactly does “import *” import?

    将 __all__ 添加到 packages.__init__:

    __all__ = ['mod']
    from packages import *
    

    模块“mod”将被导入,否则“mod”不在“packages”的命名空间中,但我无法解释为什么没有__all__的“import *”不导入“mod”。

    【讨论】:

    • 我会查看链接并进行研究。有东西我会回来的。
    • 谢谢,但仍然缺少一些东西,这是我得到的...如果 all 被定义,那么它应该导入此序列中定义的所有名称,否则它将导入所有名称,但以下划线开头的名称除外。所以在我的情况下,如果我没有定义 all ,它应该导入所有名称,包括我的 'mod' ,对吧?
    【解决方案3】:

    您可以直接在相同的包中加载模块。以下代码有效,它加载了 mod.py 中的所有模块。

    在 __init__.py 内

    from mod import *
    print hello()
    

    高效导入 - 仅加载 hello 函数

    from mod import hello
    print hello()
    

    在您的代码中,from packages import * 您告诉解释器在packages(与__init__.py 相同的目录中)中查找模块。但它在那里不存在。它存在于__init__.py 之上一个目录。 (我怀疑我的术语是错误的)

    这是一个reference,它解释了如何加载包含的包本身。

    找到了

    阅读有关 python 导入机制的内容非常有趣。 Ref1Ref2Ref3

    显然先加载父模块。例如,Ref3 指出,__init__.py 中的代码 import mod 会自动解释为 packages.mod。现在我必须找出如果你写import packages.mod会发生什么。 Ref1 更符合 python3 约定。请参阅它以获取更多信息。希望对您有所帮助。

    【讨论】:

    • 谢谢,但这不是我的问题,我可以使用其他导入语法来使打印工作。但我问的是那个 import * 应该导入所有东西,包括 ** mod **
    • 您还说名为 packages 的模块不存在,但实际上如果我这样做: from packages import mod.有用 !尝试删除此代码并运行它,它会给你错误。但是当我输入“从包导入模块”时,它可以工作。所以这意味着它在那里。我知道你的意思,包裹是上层的,这就是为什么我很困惑。它应该是“非法的”,但“from packages import mod”有效!这就是为什么我很困惑。我可能会稍微改变一下我的问题......为什么“从包导入模块”工作?
    • 好的,这很有趣。您能否指定平台操作系统和 python 版本,以便我可以重新创建场景并进行测试。我会检查的。
    • @andio 添加了一些参考,我仍然需要重新创建您的场景。
    • @andio 我在 IDE 中测试了相同的代码,同时将 packages 指定为根文件夹。现在from packages import modfrom packages.mod import * 都可以了。但是在终端内运行_init__.py 会抛出ImportError: No module named 'packages' 。这已在参考文献 1,2 和 3 中详细讨论。在调用导入之前,这些包是未知的。因此,当我们尝试从包中加载时,它会显示ImportError
    猜你喜欢
    • 2020-08-27
    • 2012-12-24
    • 2019-07-31
    • 2017-10-05
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    • 2017-02-25
    • 2021-02-05
    相关资源
    最近更新 更多