什么是__init__.py?

时间:2009-01-15 20:09:10

标签: python module package python-packaging

Python源目录中的__init__.py是什么?

11 个答案:

答案 0 :(得分:1209)

它曾经是包裹的必需部分(old, pre-3.3 "regular package",而不是newer 3.3+ "namespace package")。

Here's the documentation.

  

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

但只需单击该链接,它就会包含一个示例,更多信息以及命名空间包的说明,即没有__init__.py的包类型。

答案 1 :(得分:701)

名为__init__.py的文件用于将磁盘上的目录标记为Python包目录。 如果你有文件

mydir/spam/__init__.py
mydir/spam/module.py

mydir在您的路径上,您可以将代码导入module.py

import spam.module

from spam import module

如果删除__init__.py文件,Python将不再在该目录中查找子模块,因此导入模块的尝试将失败。

__init__.py文件通常为空,但可以用更方便的名称导出包的选定部分,保存便利功能等。 鉴于上面的示例,init模块的内容可以作为

访问
import spam

基于this

答案 2 :(得分:414)

除了将目录标记为Python包并定义__all__之外, __init__.py还允许您在包级别定义任何变量。这样做通常很方便包以类似API的方式定义将经常导入的内容。这种模式促进了对Pythonic的坚持“扁平比嵌套”更好的哲学。

一个例子

以下是我的一个项目的示例,其中我经常导入名为sessionmaker的{​​{1}}以与我的数据库进行交互。我写了一个包含几个模块的“数据库”包:

Session

我的database/ __init__.py schema.py insertions.py queries.py 包含以下代码:

__init__.py

由于我在这里定义import os from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine engine = create_engine(os.environ['DATABASE_URL']) Session = sessionmaker(bind=engine) ,我可以使用下面的语法开始一个新会话。此代码与“database”包目录内部或外部执行的代码相同。

Session

当然,这是一个小小的便利 - 另一种方法是在我的数据库包中的新文件中定义from database import Session session = Session() ,例如“create_session.py”,并使用以下命令启动新会话:

Session

进一步阅读

有一个非常有趣的reddit主题,涵盖from database.create_session import Session session = Session() 的适当用法:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

多数意见似乎是__init__.py文件应该非常薄,以避免违反“明确胜于隐性”的理念。

答案 3 :(得分:142)

__init__.py

有两个主要原因
  1. 为方便起见:其他用户无需了解您的功能在包层次结构中的确切位置。

    your_package/
      __init__.py
      file1.py/
      file2.py/
        ...
      fileN.py
    
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    
    # in file1.py
    def add():
        pass
    

    然后其他人可以通过

    调用add()
    from your_package import add
    

    不知道file1,比如

    from your_package.file1 import add
    
  2. 如果您想要初始化某些内容;例如,日志记录(应该放在顶层):

    import logging.config
    logging.config.dictConfig(Your_logging_config)
    

答案 4 :(得分:94)

__init__.py文件使Python将包含它的目录视为模块。

此外,这是要在模块中加载的第一个文件,因此您可以使用它来执行每次加载模块时要运行的代码,或者指定要导出的子模块。

答案 5 :(得分:72)

从Python 3.3开始,不再需要__init__.py将目录定义为可导入的Python包。

检查PEP 420: Implicit Namespace Packages

  

对不需要__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-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Is __init__.py not required for packages in Python 3?

答案 6 :(得分:48)

在Python中,包的定义非常简单。与Java一样,层次结构和目录结构是相同的。但是你必须在包中加__init__.py。我将使用以下示例解释__init__.py文件:

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py可以为空,只要它存在即可。它表示该目录应被视为包。当然,__init__.py也可以设置适当的内容。

如果我们在module_n1中添加一个函数:

def function_X():
    print "function_X in module_n1"
    return

跑完后:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

然后我们按照层次结构包并调用module_n1函数。我们可以在subPackage_b中使用__init__.py,如下所示:

__all__ = ['module_n2', 'module_n3']

跑完后:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

因此,使用*导入,模块包受__init__.py内容约束。

答案 7 :(得分:37)

__init__.py会将其所在的目录视为可加载模块。

对于喜欢阅读代码的用户,我在这里发表Two-Bit Alchemist's评论。

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 

答案 8 :(得分:28)

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

root\
    stuff\
         other.py

    morestuff\
         another.py

如果目录中没有此__init__.py,则无法导入other.py,因为Python不知道内容源代码的位置,也无法将其识别为包。

答案 9 :(得分:0)

__init__.py文件使导入变得容易。当软件包中包含__init__.py时,可以像这样从文件a()导入函数b.py

from b import a

但是,没有它,您将无法直接导入。您必须修改系统路径:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a

答案 10 :(得分:0)

__ init__.py允许的一件事是将模块转换为包,而无需破坏API或创建无关的嵌套名称空间或私有模块*。当我要扩展名称空间时,这会有所帮助。

如果我有一个包含util.py的文件

def foo():
   ...

然后用户将使用{p>访问foo

from util import foo

如果随后我想添加实用程序函数来进行数据库交互,并且希望它们在util下拥有自己的名称空间,则需要一个新目录**,并保持API兼容性(这样{ {1}}仍然有效),我将其称为util /。我可以像这样将util.py移至util /,

from util import foo

并在util / __ init__.py中完成

util/
  __init__.py
  util.py
  db.py

但这是多余的。不用拥有util / util.py文件,我们只需将util.py内容放入__init__.py中,用户现在就可以

from util import *

我认为这很好地突出了from util import foo from util.db import check_schema 包的__init__.py如何以与util模块类似的方式起作用

*其他答案中暗示了这一点,但我想在此突出显示
**缺乏雇用进口体操。请注意,使用与该文件相同的名称创建新软件包将无效,请参见this