
本文详解如何规范使用 src 布局避免 ModuleNotFoundError: No module named 'src',强调不将 src 写入 import 语句,而是通过可安装包 + pyproject.toml 实现稳定、可移植、符合 PEP 517 的模块解析。
本文详解如何规范使用 `src` 布局避免 `modulenotfounderror: no module named 'src'`,强调不将 `src` 写入 import 语句,而是通过可安装包 + `pyproject.toml` 实现稳定、可移植、符合 pep 517 的模块解析。
在 Python 工程实践中,“src 目录”并非一个可导入的模块名,而是一个约定俗成的源码根容器目录(source layout)。你遇到的 ModuleNotFoundError: No module named 'src' 并非环境配置失败,而是设计层面的根本性误用:from src.config import ... 这类写法违背了 Python 包管理的核心原则——src 不应出现在任何 import 路径中。
✅ 正确的 src 布局原则
根据 Python Packaging User Guide,src/ 的唯一职责是包裹实际的 Python 包(如 afrr, config 等),而非自身成为包。因此,你的目录结构应调整为:
/
├── pyproject.toml ← 替代 setup.py,现代标准
├── src/
│ └── afrr/ ← 真正的可导入包(含 __init__.py)
│ ├── __init__.py
│ ├── dumper.py
│ └── cleaner.py
│ └── config.py ← 若为独立模块(非包),可保留;若需组织为包,建议 src/myproject/config.py
│ └── tests/ ← ❌ 测试不应放在 src 内!见下文说明
└── tests/ ← ✅ 测试应与 src 平级(推荐)
└── test_afrr_dumper.py
⚠️ 关键修正:
tests/目录不应嵌套在src/下。测试代码不属于发布包内容,混入src/会导致find_packages()错误包含测试模块,污染安装包,且破坏隔离性。
✅ 正确的导入方式(修改后)
假设你将核心包命名为 afrr(即 src/afrr/ 是包),并把 config.py 移至 src/afrr/config.py 或作为独立顶层模块(如 src/config.py 且 src 配置为 package_dir),则所有导入必须基于包名,而非目录名:
# ✅ 正确:从包 afrr 导入
from afrr.dumper import dump_afrr_data
from afrr.config import PROCESSED_DIR # 若 config.py 在 src/afrr/ 下
# ✅ 或(若 config.py 在 src/ 根下且已配置 package_dir={"": "src"}):
from config import PROCESSED_DIR
❌ 错误示例(永远不要写):
from src.afrr.dumper import ... # src 不是包名 from src.config import ... # 同上
✅ 现代化可安装配置(pyproject.toml)
创建 pyproject.toml(取代 setup.py),启用 src 布局并声明包名:
[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "afrr" version = "0.1.0" dependencies = [ "pandas>=1.0.0", ] [project.optional-dependencies] test = ["pytest"] [project.urls] Homepage = "https://example.com" [tool.hatch.build.targets.sdist] include = ["src/**"] [tool.hatch.build.targets.wheel] source = "src"
然后执行:
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
pip install -e . # 安装为可编辑模式(editable install)
该命令会将 src/ 下的 afrr(及其它符合命名规则的包)注册到 Python 的 sys.path,使 import afrr 全局可用 —— 无需设置 PYTHONPATH,不依赖运行位置,跨平台稳定。
✅ 测试文件的正确位置与运行方式
将测试文件移出 src/,置于项目根目录下的 tests/:
/
├── pyproject.toml
├── src/
│ └── afrr/
│ ├── __init__.py
│ ├── dumper.py # 含 def dump_afrr_data(...)
│ └── config.py
└── tests/
└── test_afrr_dumper.py
tests/test_afrr_dumper.py 内容应为:
import pytest
from afrr.dumper import dump_afrr_data
from afrr.config import PROCESSED_DIR
def test_dump_works():
assert callable(dump_afrr_data)
assert isinstance(PROCESSED_DIR, str)
运行测试(确保在项目根目录):
pytest tests/ -v # 或指定 Python path(自动识别已安装的 afrr 包) python -m pytest tests/ -v
? 总结:三步永久解决
-
清理 import 路径:删除所有
from src.xxx,只使用真实包名(如afrr,config); -
重构目录:
src/仅作源码容器,tests/与src/平级,pyproject.toml明确source = "src"; -
可编辑安装:
pip install -e .一次配置,永久生效,支持 IDE 自动补全、调试与 CI/CD。
此方案完全规避手动环境变量、路径硬编码或 IDE 特定设置,符合 Python 社区最佳实践,也是 hatch、poetry、setuptools 等主流工具默认推荐的工程化路径。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










