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

使用__init__.py导入Python子模块

司寇照
2023-03-14
问题内容

我正在学习Python,但无法弄清楚导入的__init__.py工作方式。

我从Python教程中了解到该__init__.py文件初始化了一个程序包,并且可以在此处导入子程序包。

不过,我做错了。您能为我(以及将来的Python学习者)解释我做错了什么吗?

这是我正在尝试做的一个简化示例。

这是我的文件结构:

package
    __init__.py
    test.py
    subpackage
        __init__.py
        hello_world.py

内容hello_world.py

def do_something():
    print "Hello, world!"

subpackage/__init__.py 是空的。

package/__init__.py 包含:

import test.submodule.do_something

最后,test.py包含:

do_something()

这就是我尝试使用OSX终端和Python 3运行hello_world.py的方式:

python test.py

然后,Python引发以下错误:

NameError: name 'do_something' is not defined

问题答案:

您可能已经了解,当您导入 模块时
,解释器会创建一个新的名称空间,并使用新的名称空间作为本地和全局名称空间来执行该模块的代码。代码完成执行后,模块名称(或任何子as句中提供的名称)将绑定到刚在导入名称空间中创建并记录在其__name__in中的模块对象sys.modules

package.subpackage.module导入诸如的限定名称时,名字(package)导入本地名称空间,然后subpackage导入package的名称空间,最后module导入package.subpackage的名称空间。使用from ... import ... as ...进行导入的操作顺序相同,但是导入的对象直接绑定到导入模块名称空间中的名称。包名称未绑定在本地名称空间中这一事实并不意味着它尚未导入(如对的检查sys.modules所示)。

__init__.py软件包中的in与模块.py文件具有相同的功能。具有结构的
被写为目录,其中还可以包含任何sub_packages的模块(常规.py文件)和子目录(也包含__init__.py文件)。导入程序包时,将创建一个新的名称空间,并__init__.py使用该名称空间作为本地和全局名称空间来执行程序包的名称空间。因此,为回答您的问题,我们可以通过省略顶层软件包来删除文件存储,而顶层软件包test.py在程序运行时将永远不会被其考虑。然后看起来像这样:

test.py
subpackage/
    __init__.py
    hello_world.py

现在,subpackage不再是子包,因为我们已删除了不相关的包含包。专注于为什么do_something未定义名称可能会有所帮助。test.py不包含任何导入,因此目前尚不清楚您期望do_something如何获得意义。您可以通过使用空白使其工作subpackage/__init__.py,然后test.py读取

from subpackage.hello_world import do_something
do_something()

另外,您可以我们subpackage/__init__.py读取

from hello_world import do_something

当导入包时,它将do_somethingsubpackage名称空间内建立函数。然后使用test.py从包中导入功能的,如下所示:

from subpackage import do_something
do_something()

最后一个相同的选择__init__.py是使用test.py简单地导入(sub)包的a,然后使用相对命名来访问所需的功能:

import subpackage
subpackage.do_something()

在您的本地名称空间中访问它

空着__init__.py也可以通过test.py阅读来实现

import subpackage.hello_world
subpackage.hello_world.do_something()

甚至

from subpackage.hello_world import do_something
do_something()

如果为空,__init__.py则意味着顶级程序包名称空间将仅包含程序导入的任何子程序包的名称,这使您仅可以导入所需的子程序包。该文件确定顶级程序包的名称空间。

尽管完全可以在中定义类和函数,但
__init__.py更常见的方法是从子模块将内容导入该命名空间,以便导入者只需导入顶级包即可使用单级属性引用来访问其内容,甚至from只用于导入您想要的名称。

最终,使您保持直觉的最佳工具是清楚了解导入的工作方式及其各种形式对导入名称空间的影响。



 类似资料:
  • 问题内容: 我一直在阅读有关文件的功能。据说我们在包含模块的文件夹中需要一个空文件,以便可以导入这些模块。但是,我尝试将文件夹路径添加到PYTHONPATH(Windows 7中为环境变量)。尽管此文件夹不包含文件,但我仍然可以从该文件夹导入模块。您能否解释一下在不存在的情况下如何导入这些模块? 谢谢, 最好的祝福 问题答案: 把一个文件夹变成一个包。这对于创建某种模块层次结构很有用,您可以在其中

  • 问题内容: 我试图了解关于Python(v2.7)导入机制的最佳实践。我有一个项目开始有所增长,可以说我的代码如下组织: 包名称为,在其下方,我有一个模块,其中包含该类的代码。因此,我对包,模块和类使用了相同的名称,但起初可能不太聪明。 为空,需要导入类,因此文件的一部分如下所示: 但是我后来又重新考虑了这一点,并且我认为最好在文件中包含所有导入内容。因此,我现在看起来像: 而我只需要导入: 虽然

  • 问题内容: 我正在使用Flask Framework 构建网站,其中有一个文件夹,其中有一些python文件和脚本(我想您将此文件夹称为模块吗?)。在 init .py文件中,我有一行话: 我现在想在此文件夹中的其他脚本中使用。通常,我会使用进行此操作,但这样做似乎不合适,更不用说pythonic了。此外,由于它在文件中,因此我认为应该以某种方式对整个文件夹/模块进行初始化。 有人知道如何使用该文

  • 问题内容: 我在理解项目中python文件的使用场景或设计目标时遇到了困难。 假设我有“模型”目录(称为包),其中包含以下文件 我发现了两种使用方法: 我有需要使用一个共同的定义,,。我可以用作所有* model.py类的基础/通用定义吗?这意味着我必须导入。 或者,应当具有自己导入的solrmodel.py,mongomodel.py,samodel.py的定义,并且它允许像这样的类或函数的轻松

  • init.py

  • init.py 指定导入该包时,仅导入 Client 类,代码如下: __all__ = ['Client'] from heatclient.v1.client import Client