根目录放__init__.py通常没必要且错误:它使项目被识别为包,破坏pytest/unittest模块发现、导致相对导入崩溃;仅当项目需作为可安装包发布且用pip install -e .时才考虑,但更推荐将包置于src/子目录。

根目录下放空的 __init__.py 通常**没必要,而且多数时候是错的**——它会让 Python 把整个项目当成一个包,反而破坏模块发现逻辑、干扰测试运行、导致 from . import xxx 报错。
为什么根目录加 __init__.py 会破坏 pytest / unittest 运行?
pytest 默认把当前工作目录(即项目根目录)加入 sys.path,再按文件路径导入测试模块。一旦根目录有 __init__.py,Python 就把它识别为包,而 pytest 会尝试以包方式导入测试文件(比如 python -m pytest tests/test_api.py),此时 test_api.py 的 __package__ 变成 "" 或 None,相对导入直接崩溃:
SystemError: Parent module '' not loaded, cannot perform relative import- 即使测试文件里没写
from .. import xxx,只要它所在目录被当成包,__package__就可能被错误推导 - 某些 IDE(如 PyCharm)在“Run as pytest”时也会因该文件误判包结构,跳过测试发现
什么情况下根目录才需要 __init__.py?
仅当你的项目本身要被其他项目当作可安装包使用,且你明确用 setuptools 打包发布(比如 pip install -e .),才可能考虑在根目录放 __init__.py ——但更推荐的做法是:把真正要发布的包放在子目录里(如 src/mylib/),根目录保持干净。
- ✅ 推荐结构:
myproject/(无__init__.py) →src/mylib/__init__.py(有) →tests/(无) - ❌ 反模式:
myproject/__init__.py+myproject/main.py+myproject/tests/;这会让import myproject成立,但pytest和python -m行为变得不可预测 - 构建工具如
poetry或hatch默认不依赖根目录__init__.py,它们靠pyproject.toml中的[project]配置定位源码
__init__.py 应该出现在哪些位置?
只在**明确需要被 import 的子目录**里放 __init__.py,比如:
立即学习“Python免费学习笔记(深入)”;
- 业务代码包:
app/、api/、models/、utils/ - 测试辅助模块:
tests/conftest.py所在的tests/目录(如果测试里用了from tests.utils import fake_db) - 子包嵌套:
api/v1/__init__.py、api/v2/__init__.py - 空文件完全 OK,不需要写任何代码;但若想简化导入(如让
from api import login可用),就在对应__init__.py里写from .login_api import login
最容易被忽略的一点:根目录有没有 __init__.py,和你的代码能不能被导入,根本无关——真正起作用的是 Python 如何解析 sys.path 和模块路径,而不是根目录是否“自封为包”。别被旧教程带偏,删掉它,世界更清净。


















