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


当前回答

__init__.py文件使导入变得容易。当包中存在__init__.py时,可以从文件b.py导入函数a(),如下所示:

from b import a

但是,如果没有它,就不能直接导入。您必须修改系统路径:

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

from b import a

其他回答

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

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

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

import spam.module

or

from spam import module

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

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

import spam

基于此

在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

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

如果您使用的是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.一个硬编码的库来加载特定文件,而不是其他文件。对于这些情况,这是一种选择。

__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在没有__init__.py文件的情况下工作,但仍应包含一个。

它指定目录应被视为一个包,因此包含它(即使它是空的)。

还有一种情况是,您可能实际使用__init__.py文件:

假设您具有以下文件结构:

main_methods 
    |- methods.py

而methods.py包含以下内容:

def foo():
    return 'foo'

要使用foo(),您需要以下选项之一:

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

也许您需要(或希望)将methods.py保存在main_methods(例如运行时/依赖项)中,但您只希望导入main_method。


如果将methods.py的名称更改为__init__.py,则可以通过导入main_methods来使用foo():

import main_methods
print(main_methods.foo()) # Prints 'foo'

这是因为__init__.py被视为包的一部分。


一些Python包实际上做到了这一点。一个例子是JSON,其中运行import JSON实际上是从JSON包中导入__init__.py(请参阅此处的包文件结构):

源代码:Lib/json/__init__.py