__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
其他回答
自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文件使Python将包含它的目录视为模块。
此外,这是模块中要加载的第一个文件,因此您可以使用它来执行每次加载模块时要运行的代码,或者指定要导出的子模块。
除了将目录标记为Python包并定义__all__之外,__init__.py还允许您在包级别定义任何变量。如果包以类似API的方式定义了将频繁导入的内容,那么这样做通常很方便。这种模式促进了对Pythonic“扁平优于嵌套”哲学的坚持。
一个例子
这里是我的一个项目中的一个示例,其中我经常导入一个名为Session的sessionmaker来与我的数据库交互。我编写了一个包含几个模块的“数据库”包:
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)
因为我在这里定义了会话,所以可以使用下面的语法启动新会话。该代码将与从“数据库”包目录内部或外部执行的代码相同。
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有两个主要原因
为了方便:其他用户不需要知道您的函数在包层次结构(文档)中的确切位置。您的程序包(_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在没有__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
推荐文章
- 将Pandas或Numpy Nan替换为None以用于MysqlDB
- 使用pandas对同一列进行多个聚合
- 使用Python解析HTML
- django MultiValueDictKeyError错误,我如何处理它
- 如何在for循环期间修改列表条目?
- 我如何在Django中创建一个鼻涕虫?
- 没有名为'django.core.urlresolvers'的模块
- 蟒蛇导出环境文件
- Django - makemigrations -未检测到任何更改
- SQLAlchemy:引擎、连接和会话差异
- 在Python Pandas中删除多个列中的所有重复行
- 更改pandas DataFrame中的特定列名
- 将Pandas多索引转换为列
- 熊猫在每组中获得最高的n个记录
- 熊猫数据帧得到每组的第一行