__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允许的一件事是将模块转换为包,而不破坏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模块类似
*这在其他答案中有所暗示,但我想在这里强调一下**没有采用进口体操。请注意,创建与文件同名的新包是行不通的,请参见
__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
它曾经是包的必需部分(旧的3.3之前的“常规包”,而不是更新的3.3+“命名空间包”)。
这是文档。
Python定义了两种类型的包,常规包和命名空间包。常规包是Python 3.2和更早版本中存在的传统包。常规包通常实现为包含__init__.py文件的目录。导入常规包时,将隐式执行__init__.py文件,它定义的对象将绑定到包的命名空间中的名称。__init__.py文件可以包含任何其他模块都可以包含的Python代码,并且Python将在导入模块时向模块添加一些附加属性。
但只需单击链接,它包含一个示例、更多信息和对命名空间包的解释,这是一种没有__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 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.一个硬编码的库来加载特定文件,而不是其他文件。对于这些情况,这是一种选择。
推荐文章
- 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中重置生成器对象