什么是__init__.py?

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

这是一个包的一部分。 这里是文档。

需要使用__init__.py文件来使Python将目录视为包含包; 这样做是为了防止具有通用名称的目录(例如string )无意中隐藏模块searchpath中稍后(更深)发生的有效模块。 在最简单的情况下, __init__.py可以只是一个空文件,但它也可以执行包的初始化代码或设置__all__variables,稍后介绍。

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

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

mydir在你的path上,你可以在module.py导入代码

 import spam.module 

要么

 from spam import module 

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

__init__.py文件通常是空的,但是可以用来以更方便的名称导出包的选定部分,保存便利function等等。以上例子中,init模块的内容可以被访问为

 import spam 

基于此

除了将目录标记为Python包并定义__all____init__.py允许您在包级别定义任何variables。 这样做通常很方便,如果一个包定义了一些经常导入的东西,就像API一样。 这种模式促进了坚持Pythonic“扁平优于嵌套”的理念。

一个例子

下面是我的一个项目的例子,我经常导入一个名为Sessionsessionmaker与我的数据库进行交互。 我用几个模块编写了一个“数据库”包:

 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) 

由于我在这里定义Session ,所以我可以使用下面的语法开始一个新的会话。 这个代码将从“数据库”包目录的内部或外部执行。

 from database import Session session = Session() 

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

 from database.create_session import Session session = Session() 

进一步阅读

有一个非常有趣的reddit线程覆盖了__init__.py适当使用:

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

大多数人的意见似乎是__init__.py文件应该是非常薄的,以避免违反“明确优于暗含”的哲学。

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

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

__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) 

在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 

因此,使用*import,模块包是受__init__.py内容。

__init__.py将把它所在的目录当作一个可加载的模块。

对于喜欢阅读代码的人,我把这里的两位炼金术士的评论放在这里。

 $ 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 >>> 

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

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

本地支持不需要__init__.py标记文件的软件包目录,并且可以自动跨越多个path段(受到各种第三方软件包的启发,如PEP 420所述 )

这是testing:

 $ 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/
Python 3中的包不需要__init__.py吗?

它有利于导入其他的python文件。 当你把这个文件放到一个包含其他py文件的目录(比如说东西)时,你可以做一些东西,比如import stuff.other。

 root\ stuff\ other.py morestuff\ another.py 

如果没有这个__init__.py目录内的东西,你不能导入other.py,因为Python不知道东西的源代码在哪里,无法识别它作为一个包。