__init__.py在Python源目录中用于什么?
当前回答
自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文件。当您将此文件放置在包含其他py文件的目录(比如stuff)中时,可以执行类似importstuff.other的操作。
root\
stuff\
other.py
morestuff\
another.py
如果在目录中没有这个__init__.py,您就无法导入other.py,因为Python不知道这些东西的源代码在哪里,也无法将其识别为一个包。
__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模块类似
*这在其他答案中有所暗示,但我想在这里强调一下**没有采用进口体操。请注意,创建与文件同名的新包是行不通的,请参见
除了将目录标记为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的文件用于将磁盘上的目录标记为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
基于此
推荐文章
- Numpy Max vs amax vs maximum
- 我应该在.gitignore文件中添加Django迁移文件吗?
- 每n行有熊猫
- 实例属性attribute_name定义在__init__之外
- 如何获取在Python中捕获的异常的名称?
- 第一次出现的值大于现有值的Numpy
- 如何从Python函数中返回两个值?
- 前一个月的Python日期
- Python中方括号括起来的列表和圆括号括起来的列表有什么区别?
- Python日志记录不输出任何东西
- 每n秒运行特定代码
- SQLAlchemy是否有与Django的get_or_create等价的函数?
- 如何将python datetime转换为字符串,具有可读格式的日期?
- 美丽的汤和提取div及其内容的ID
- 在Python中重置生成器对象