Python中__init__.py文件的作用

Python中__init__.py文件的作用

技术背景

在Python中,__init__.py 文件曾经是Python包(在Python 3.3之前的“常规包”)的必要组成部分。Python定义了两种类型的包:常规包和命名空间包。常规包通常是一个包含 __init__.py 文件的目录,当导入该包时,__init__.py 文件会被隐式执行,其定义的对象会绑定到包的命名空间中。而从Python 3.3开始,引入了隐式命名空间包(PEP 420),不再要求使用 __init__.py 文件来定义可导入的Python包。

实现步骤

标记目录为Python包

如果目录结构如下:

1
2
3
4
mydir/
spam/
__init__.py
module.py

mydir 在Python的搜索路径中时,可以使用以下方式导入 module.py 中的代码:

1
import spam.module

或者

1
from spam import module

若移除 __init__.py 文件,Python将不再将该目录视为包,尝试导入模块将会失败。

包级变量定义与便捷导入

在包中频繁使用的对象可以在 __init__.py 中定义,方便其他模块导入。例如,有如下包结构:

1
2
3
4
5
database/
__init__.py
schema.py
insertions.py
queries.py

__init__.py 中定义数据库会话:

1
2
3
4
5
6
7
import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

在其他模块中可以直接导入 Session

1
2
from database import Session
session = Session()

使用 __all__ 控制导入

__init__.py 中的 __all__ 变量可以控制使用 from package import * 时导入的子模块。例如,在 subPackage_b__init__.py 中:

1
__all__ = ['module_n2', 'module_n3']

当执行 from package_x.subPackage_b import * 时,只有 module_n2module_n3 会被导入。

核心代码

定义包级变量

1
2
3
4
5
6
7
8
# database/__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)

使用 __all__ 控制导入

1
2
# subPackage_b/__init__.py
__all__ = ['module_n2', 'module_n3']

包初始化代码

1
2
3
# pymodlib/__init__.py
print(f'Invoking __init__.py for {__name__}')
pystructures = ['for_loop', 'while__loop', 'ifCondition']

最佳实践

  • 保持 __init__.py 简洁:遵循“显式优于隐式”的原则,避免在 __init__.py 中写入过多复杂代码。
  • 使用 __all__ 控制导入:当需要控制 from package import * 的行为时,使用 __all__ 变量明确指定要导入的子模块。
  • 定义常用对象:将频繁使用的对象定义在 __init__.py 中,方便其他模块导入。

常见问题

Python 3.3之后是否还需要 __init__.py

从Python 3.3开始,__init__.py 不再是定义可导入Python包的必需文件,但为了明确指示该目录是一个包,建议仍然包含它,即使它是空的。

如何在Python 2中加载同级文件

在Python 2中,如果要加载同级文件,可以将当前文件的父目录添加到系统路径中:

1
2
3
4
5
6
7
import os
import sys
dir_path = os.path.dirname(__file__)
sys.path.insert(0, dir_path)

import cheese
from vehicle_parts import *

不过,建议尽量使用 __init__.py 文件来管理包。


Python中__init__.py文件的作用
https://119291.xyz/posts/2025-05-09.python-init-py-file-usage/
作者
ww
发布于
2025年5月9日
许可协议