__init__.py在Python源目录中用于什么?


当前回答

如果您使用的是Python 2,并且希望加载文件的同级文件,那么只需将文件的父文件夹添加到会话的系统路径中即可。它的行为与当前文件是init文件的情况大致相同。

import os
import sys
dir_path = os.path.dirname(__file__)
sys.path.insert(0, dir_path)

之后,相对于文件目录的常规导入将正常工作。例如。

import cheese
from vehicle_parts import *
# etc.

一般来说,您希望使用一个合适的init.py文件,但在处理遗留代码时,您可能会遇到f.ex.一个硬编码的库来加载特定文件,而不是其他文件。对于这些情况,这是一种选择。

其他回答

它曾经是包的必需部分(旧的3.3之前的“常规包”,而不是更新的3.3+“命名空间包”)。

这是文档。

Python定义了两种类型的包,常规包和命名空间包。常规包是Python 3.2和更早版本中存在的传统包。常规包通常实现为包含__init__.py文件的目录。导入常规包时,将隐式执行__init__.py文件,它定义的对象将绑定到包的命名空间中的名称。__init__.py文件可以包含任何其他模块都可以包含的Python代码,并且Python将在导入模块时向模块添加一些附加属性。

但只需单击链接,它包含一个示例、更多信息和对命名空间包的解释,这是一种没有__init__.py的包。

它有助于导入其他python文件。当您将此文件放置在包含其他py文件的目录(比如stuff)中时,可以执行类似importstuff.other的操作。

root\
    stuff\
         other.py

    morestuff\
         another.py

如果在目录中没有这个__init__.py,您就无法导入other.py,因为Python不知道这些东西的源代码在哪里,也无法将其识别为一个包。

__init__.py有两个主要原因

为了方便:其他用户不需要知道您的函数在包层次结构(文档)中的确切位置。您的程序包(_P)/__初始__.py文件1.py文件2.py...文件N.py#在__init__.py中从.file1导入*从.file2导入*...从.fileN导入*#在file1.py中def add():通过然后其他人可以调用add()从您的_package导入添加不知道file1的内部函数,例如从您的_package.file1导入添加如果你想初始化一些东西;例如,日志记录(应该放在顶层):导入logging.configlogging.config.dictConfig(Your_logging_config)

自Python 3.3以来,__init__.py不再需要将目录定义为可导入的Python包。

检查PEP 420:隐式命名空间包:

对不需要__init__.py标记文件并且可以自动跨越多个路径段的包目录的本地支持(受PEP 420中描述的各种第三方命名空间包方法的启发)

测试如下:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

参考文献:https://docs.python.org/3/whatsnew/3.3.html#pep-420个隐式命名空间包https://www.python.org/dev/peps/pep-0420/Python 3中的包是否不需要__init__.py?

__init__.py允许的一件事是将模块转换为包,而不破坏API或创建无关的嵌套命名空间或私有模块*。这有助于我扩展命名空间。

如果我有一个包含

def foo():
    ...

然后用户将使用

from util import foo

如果我想为数据库交互添加实用程序函数,并且希望它们在util下有自己的命名空间,那么我需要一个新目录**,并且为了保持API兼容性(这样从util import foo仍然可以工作),我将其称为util/。我可以像这样将util.py移动到util/中,

util/
  __init__.py
  util.py
  db.py

在util/__init__.py中

from util import *

但这是多余的。我们可以将util.py内容放在__init__.py中,而不是使用util/util.py文件,用户现在可以

from util import foo
from util.db import check_schema

我认为这很好地突出了util包的__init__.py的作用方式与util模块类似

*这在其他答案中有所暗示,但我想在这里强调一下**没有采用进口体操。请注意,创建与文件同名的新包是行不通的,请参见