文章目录
-
- 前言
- [一、init.py 到底是什么?](#一、init.py 到底是什么?)
- [二、init.py 的五大核心作用(2026最新版)](#二、init.py 的五大核心作用(2026最新版))
-
- [2.1 作用一:声明文件夹为Python包(基础)](#2.1 作用一:声明文件夹为Python包(基础))
- [2.2 作用二:控制包的导入暴露(all 变量)](#2.2 作用二:控制包的导入暴露(all 变量))
- [2.3 作用三:简化导入路径(最实用的工程技巧)](#2.3 作用三:简化导入路径(最实用的工程技巧))
- [2.4 作用四:包初始化逻辑(启动时执行)](#2.4 作用四:包初始化逻辑(启动时执行))
- [2.5 作用五:隐藏内部实现,对外提供稳定API](#2.5 作用五:隐藏内部实现,对外提供稳定API)
- [三、Python 3.10+ 下 init.py 的新变化(2026重点)](#三、Python 3.10+ 下 init.py 的新变化(2026重点))
-
- [3.1 空 init.py 完全合法](#3.1 空 init.py 完全合法)
- [3.2 命名空间包不需要 init.py,但不推荐业务使用](#3.2 命名空间包不需要 init.py,但不推荐业务使用)
- [3.3 init.py 中禁止写复杂业务逻辑](#3.3 init.py 中禁止写复杂业务逻辑)
- [3.4 推荐搭配 pyproject.toml 使用](#3.4 推荐搭配 pyproject.toml 使用)
- [四、init.py 最佳实践(直接照抄用)](#四、init.py 最佳实践(直接照抄用))
-
- [4.1 最简空包(推荐)](#4.1 最简空包(推荐))
- [4.2 带 all 控制导入](#4.2 带 all 控制导入)
- [4.3 简化导入(最常用)](#4.3 简化导入(最常用))
- [4.4 带版本信息](#4.4 带版本信息)
- [4.5 懒加载高级写法(2026流行)](#4.5 懒加载高级写法(2026流行))
- [五、新手最容易踩的 init.py 坑](#五、新手最容易踩的 init.py 坑)
-
- [5.1 坑1:忘记写 init.py,导入失败](#5.1 坑1:忘记写 init.py,导入失败)
- [5.2 坑2:循环导入](#5.2 坑2:循环导入)
- [5.3 坑3:all 写错,导致 import * 失效](#5.3 坑3:all 写错,导致 import * 失效)
- [5.4 坑4:在 init.py 写大量代码,导致导入极慢](#5.4 坑4:在 init.py 写大量代码,导致导入极慢)
- [5.5 坑5:把 init.py 当成普通业务文件用](#5.5 坑5:把 init.py 当成普通业务文件用)
- 六、真实项目结构示例(2026标准)
- [七、总结:一句话记住 init.py](#七、总结:一句话记住 init.py)
P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,[传送门https://blog.csdn.net/HHX_01\],(https://blog.csdn.net/HHX_01/article/details/159613021)
前言
很多刚学Python的小伙伴都会遇到一个灵魂拷问:为什么我写的模块别人能导入,我自己写的包就死活导入失败? 排查半天,最后发现只是少了一个 __init__.py 文件。
在Python开发中,__init__.py 可以说是最常见又最容易被忽略的文件。尤其是2026年现在,Python 3.10+已经全面普及,命名空间包、pyproject.toml、importlib 等新特性层出不穷,很多人还在用十年前的旧写法,不仅代码臃肿,还容易踩坑。
这篇文章我就用最通俗、最接地气的方式,把 __init__.py 的作用、用法、新版变化、最佳实践、避坑指南一次性讲透。不管你是刚入门的小白,还是工作多年的老开发,都能从中找到能直接用在项目里的干货。
一、init.py 到底是什么?
简单一句话:
__init__.py 是Python用来标识一个文件夹为「标准包(Package)」的标记文件。
在没有 __init__.py 之前,一个文件夹只是普通文件夹,Python 不会把它当成包来识别,你也无法正常 import 里面的模块。
举个最直观的例子:
my_project/
├── utils/
│ ├── math.py
│ └── string.py
└── main.py
如果你在 main.py 里写:
python
import utils.math
Python 会直接报错:ModuleNotFoundError。
但只要在 utils 文件夹里加一个空的 __init__.py:
my_project/
├── utils/
│ ├── __init__.py
│ ├── math.py
│ └── string.py
└── main.py
再导入就完全正常了。
这就是 __init__.py 最基础、最核心的作用:声明这是一个Python包。
二、init.py 的五大核心作用(2026最新版)
很多老教程只讲"标记包",但在现代Python开发中,__init__.py 的作用远不止于此。下面我按实际开发频率从高到低,把五大核心作用讲清楚。
2.1 作用一:声明文件夹为Python包(基础)
这是最原始、最必须的作用。只要你想让一个文件夹变成可导入的包,就必须有 __init__.py。
注意:
从 Python 3.3+ 开始,引入了命名空间包(Namespace Package) ,可以没有 __init__.py 也能导入。但在实际工程、发布包、公司项目 中,99% 仍然推荐使用 __init__.py,因为命名空间包有很多隐式坑,不适合小白和标准工程。
2026年的主流规范依然是:
业务项目必须写 __init__.py,库开发建议保留。
2.2 作用二:控制包的导入暴露(all 变量)
这是 __init__.py 最常用、最重要的功能,没有之一。
你一定见过这种写法:
python
# utils/__init__.py
__all__ = ["math", "string"]
它的作用是:
当别人使用 from utils import * 时,只导入 __all__ 列表里的模块。
没有 __all__,* 导入行为是混乱且不可控的。
真实开发场景示例:
python
# utils/math.py
def add(a, b):
return a + b
def minus(a, b):
return a - b
# utils/string.py
def upper(s):
return s.upper()
# utils/__init__.py
__all__ = ["math", "string"]
在外部使用:
python
from utils import *
print(math.add(1, 2))
print(string.upper("hello"))
非常干净、规范。
如果没有 __all__,import * 可能会导入内部变量、测试函数、私有模块,导致命名冲突。
2.3 作用三:简化导入路径(最实用的工程技巧)
这是中高级开发者必用的技巧,可以让用户不用写冗长的层级导入。
比如原本结构:
my_lib/
├── __init__.py
├── core/
│ ├── __init__.py
│ ├── calculator.py
calculator.py 里有一个 Calculator 类。
正常导入要写:
python
from my_lib.core.calculator import Calculator
又臭又长。
我们可以在 my_lib/core/__init__.py 里写:
python
from .calculator import Calculator
再在 my_lib/__init__.py 写:
python
from .core import Calculator
外部用户只需要:
python
from my_lib import Calculator
层级被彻底抹平,使用体验大幅提升。
这也是2026年主流开源库(如FastAPI、Pandas、Polars)的标准做法。
2.4 作用四:包初始化逻辑(启动时执行)
__init__.py 在包第一次被导入时会自动执行,所以可以用来做初始化操作。
例如:
- 加载配置
- 初始化日志
- 检查环境
- 注册插件
- 预加载模型
示例:
python
# my_lib/__init__.py
import logging
import os
# 包初始化时执行
print("my_lib 正在初始化...")
# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("my_lib")
# 读取环境配置
VERSION = "1.0.0"
DEBUG = os.getenv("MY_LIB_DEBUG", "0") == "1"
外部导入时:
python
import my_lib
# 自动输出:my_lib 正在初始化...
注意:
初始化逻辑不要太重,2026年的最佳实践是尽量懒加载,避免拖慢导入速度。
2.5 作用五:隐藏内部实现,对外提供稳定API
大型项目一定会区分:
- 公开接口(public):给用户用
- 内部实现(private):自己用,不对外暴露
__init__.py 就是最好的隔离层。
示例结构:
ai_toolkit/
├── __init__.py
├── _internals/
│ ├── __init__.py
│ ├── engine.py
│ └── utils.py
└── api.py
_internals 是内部实现,不希望用户直接导入。
我们在 ai_toolkit/__init__.py 只暴露公开API:
python
from .api import ModelInfer, Tokenizer
用户只能这样用:
python
from ai_toolkit import ModelInfer
无法直接导入 _internals,保证了代码安全与后续重构自由。
三、Python 3.10+ 下 init.py 的新变化(2026重点)
到了2026年,Python 3.10及以上版本成为绝对主流,__init__.py 也有了很多现代化变化。
3.1 空 init.py 完全合法
很多人强迫症喜欢删空文件,但保留空 __init__.py 是现代Python标准规范,不影响性能,也不冗余。
3.2 命名空间包不需要 init.py,但不推荐业务使用
命名空间包适合分发包、多模块联合包,但业务系统用起来容易出现:
- 导入路径混乱
- 无法控制
__all__ - 无法做初始化
- IDE识别错乱
所以公司项目一律用传统带 init.py 的包。
3.3 init.py 中禁止写复杂业务逻辑
现代Python强调懒加载 ,__init__.py 只做三件事:
- 导出公开API
- 定义元信息(version 、author)
- 极简初始化
不要再写循环、IO、网络请求、 heavy计算在 __init__.py 里。
3.4 推荐搭配 pyproject.toml 使用
2026年打包标准是 pyproject.toml,__init__.py 负责运行时导出,pyproject.toml 负责构建时配置。
示例:
toml
[project]
name = "my_utils"
version = "0.1.0"
在 __init__.py 中:
python
__version__ = "0.1.0"
保持一致即可。
四、init.py 最佳实践(直接照抄用)
我把2026年工业界最标准的写法整理成模板,你可以直接复制到项目中。
4.1 最简空包(推荐)
python
# __init__.py
# 空文件即可
4.2 带 all 控制导入
python
__all__ = [
"math",
"string",
"file"
]
4.3 简化导入(最常用)
python
from .core import Engine
from .api import predict
from .utils import Config
__all__ = ["Engine", "predict", "Config"]
4.4 带版本信息
python
__version__ = "1.0.0"
__author__ = "AI开发者"
from .model import MyModel
__all__ = ["MyModel"]
4.5 懒加载高级写法(2026流行)
避免启动慢:
python
from importlib import lazy_import
__all__ = ["Model"]
Model = lazy_import(".model").Model
导入时不加载,第一次使用才加载。
五、新手最容易踩的 init.py 坑
5.1 坑1:忘记写 init.py,导入失败
这是小白第一大坑。只要是包,必须加 __init__.py。
5.2 坑2:循环导入
在 __init__.py 导入子模块,子模块又导入包,导致死循环。
解决方案:
- 简化
__init__.py - 使用懒加载
- 调整依赖关系
5.3 坑3:all 写错,导致 import * 失效
__all__ 是字符串列表,写错名字就会找不到模块。
5.4 坑4:在 init.py 写大量代码,导致导入极慢
现代Python追求极速导入,初始化逻辑尽量丢到内部模块。
5.5 坑5:把 init.py 当成普通业务文件用
它是包声明文件,不是业务逻辑文件,不要写函数实现。
六、真实项目结构示例(2026标准)
给你一个可直接用于生产的完整结构:
my_ai_project/
├── my_ai/
│ ├── __init__.py # 导出API
│ ├── core/
│ │ ├── __init__.py
│ │ └── engine.py
│ ├── utils/
│ │ ├── __init__.py
│ │ ├── log.py
│ │ └── config.py
│ └── api.py
├── pyproject.toml
└── main.py
my_ai/__init__.py:
python
__version__ = "1.0.0"
from .core.engine import AIEngine
from .api import inference
from .utils.config import Settings
__all__ = ["AIEngine", "inference", "Settings"]
外部使用:
python
from my_ai import AIEngine, inference, Settings
干净、优雅、专业。
七、总结:一句话记住 init.py
- 标记包:告诉Python这是一个包
- 控制暴露 :用
__all__管理导入 - 简化路径:让用户少写层级
- 初始化:包启动时执行一次
- 隔离实现:保护内部代码
2026年的Python开发,__init__.py 不是过时产物,而是包结构设计的核心枢纽。写好它,你的项目结构会清晰十倍,别人用你的包也会爽十倍。
只要按照本文的规范去写,你再也不会遇到导入失败、结构混乱、规范不统一的问题。
P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,[传送门https://blog.csdn.net/HHX_01\],(https://blog.csdn.net/HHX_01/article/details/159613021)