当前位置: 首页 > 图灵资讯 > 行业资讯> Python 项目中正确使用 src 目录结构与模块导入的完整指南

Python 项目中正确使用 src 目录结构与模块导入的完整指南

来源:图灵python
时间: 2026-09-01 16:12:24

本文详细说明了如何规范使用 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.pysrc 配置为 package_dir),所有导入必须基于包名,而不是目录名:

立即学习“Python免费学习笔记(深入);

# ✅ 正确:从包 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 布局并声明包名:

Python数据分析助手

为业务和科研数据的快速处理提供Python数据清理、统计分析和可视化建议。

下载

[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"

然后执行:

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
? 总结:永久解决三个步骤
  1. 清理 import 路径:删除一切 from src.xxx,只使用真实包名(如 afrr, config);
  2. 重构目录:src/ 仅作为源码容器,tests/src/ 平级,pyproject.toml 明确 source = "src"
  3. 可编辑安装:pip install -e . 配置,永久生效,支持 IDE 自动补充、调试和 CI/CD。

该方案完全避免了手动环境变量、路径硬编码或 IDE 具体设置,符合 Python 最好的社区实践,也是 hatchpoetrysetuptools 等主流默认推荐工程路径。