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

模块导入和__init__.py在Python中

金钧
2023-03-14
问题内容

我试图了解关于Python(v2.7)导入机制的最佳实践。我有一个项目开始有所增长,可以说我的代码如下组织:

foo/
    __init__.py
    Foo.py
    module1.py
    module2.py
    module3.py

包名称为foo,在其下方,我有一个模块Foo.py,其中包含该类的代码Foo。因此,我对包,模块和类使用了相同的名称,但起初可能不太聪明。

__init__.py为空,Foo需要导入类,module1, module2 and module3因此Foo.py文件的一部分如下所示:

# foo/Foo.py

import module1
import module2
import module3

class Foo(object):
    def __init__(self):
....
....
if __name__ == '__main__':
    foo_obj = Foo()

但是我后来又重新考虑了这一点,并且我认为最好在__init__.py文件中包含所有导入内容。因此,我__init__.py现在看起来像:

# foo/__init__.py

import Foo
import module1
import module2
import module3
....
....

而我Foo.py只需要导入foo

# foo/Foo.py

import foo

虽然这很方便,因为它是一个班轮,但我有点担心它可能会产生循环进口。我的意思是,当脚本Foo.py运行时,它将导入它可以导入的所有内容,然后__init__.py将被调用并Foo.py再次导入(这是正确的吗?)。此外,对于包,模块和类使用相同的名称会使情况更加混乱。

我这样做的方式有意义吗?还是我在找麻烦?


问题答案:

如果仅遵守一些流行的python约定和标准,您可以做一些事情来改善组织。

如果您搜索此主题,则不可避免地会遇到建议PEP8准则的人们。这些是组织python代码的事实上的规范标准。

模块应使用简短的全小写名称。如果模块名称可以提高可读性,则可以在模块名称中使用下划线。尽管不鼓励使用下划线,但Python软件包也应使用短小写全名。

根据这些准则,您的项目模块应命名为:

foo/
    __init__.py
    foo.py
    module1.py
    module2.py
    module3.py

我发现通常最好避免不必要地导入模块,__init__.py除非您出于命名空间原因这样做。例如,如果您希望包的名称空间看起来像这样

from foo import Foo

代替

from foo.foo import Foo

然后把

from .foo import Foo

在你的__init__.py。随着包的变大,某些用户可能不想使用所有子包和模块,因此通过隐式将它们导入到中来强迫用户等待所有这些模块加载是没有意义的__init__.py。此外,你要考虑你是否甚至想module1module2module3为您的外部API的一部分。它们仅由Foo最终用户使用而不打算供最终用户使用吗?如果它们仅在内部使用,则不要将它们包括在__init__.py

我还建议使用绝对或显式相对导入来导入子模块。例如,在foo.py

绝对

from foo import module1
from foo import module2
from foo import module3

显式相对

from . import module1
from . import module2
from . import module3

这样可以防止其他软件包和模块的任何命名问题。如果您决定支持Python3,也将变得更加容易,因为Python3不支持您当前使用的隐式相对导入语法。

另外,您包中的文件通常不应包含

if __name__ == '__main__'

这是因为将文件作为脚本运行意味着该文件将不被视为属于该文件包的一部分,因此将无法进行相对导入。

向用户提供可执行脚本的最佳方法是使用scriptsconsole_scripts功能setuptools。根据使用的方法,组织脚本的方式可以有所不同,但是我通常这样组织我的脚本:

foo/
    __init__.py
    foo.py
    ...
scripts/
     foo_script.py
setup.py


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

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

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

  • 我是Python新手,我仍然无法理解为什么我们需要一个文件来导入模块。我已经看过了其他的问题和答案,比如这个。 让我困惑的是,我可以在没有的情况下导入我的模块,那么为什么我需要它呢? 以我为例,, index.py, 模块/hello/hello.py, 模块/Hello/HelloWorld.py, 后果 只需要这两条线, 没有任何。有人能解释为什么它是这样工作的吗? 如果是正确的方法,我应该在

  • 问题内容: 我正在尝试组织一些模块供我自己使用。我有这样的事情: 在中,如果要导入lib,我想定义一些要使用的类。但是,如果不将这些类分离到文件中并将其导入中,我似乎无法弄清楚。 与其说: 我想要这样的东西: 有可能吗,还是我必须将类分成另一个文件? 编辑 好的,如果我从另一个脚本导入lib,则可以访问Helper类。如何从settings.py访问Helper类? 此处的示例描述了包装内参考。我

  • init.py