理解src布局与tests分离的项目结构
传统的Python项目常将源码直接置于根目录,导致测试文件、配置文件与业务代码混杂。采用src布局后,所有生产环境代码统一放入src/项目名/目录下,而tests/目录专门存放单元测试与集成测试脚本。这种分离的核心优势在于明确边界:src目录仅包含可发布的业务逻辑,tests目录仅负责验证。相比根目录布局,src布局能有效避免Python解释器在开发时意外将当前工作目录加入sys.path,从而防止隐式导入引发的路径冲突。此外,在构建分发包时,构建工具默认只打包src下的内容,彻底杜绝测试代码、临时脚本或敏感配置被误发布到PyPI的风险。规范的层级结构也为CI/CD流水线提供了清晰的执行上下文,使代码审查与依赖管理更加可控。

创建标准src与tests目录并配置项目
从零搭建标准结构时,首先在项目根目录执行mkdir -p src/myapp tests,并在src/myapp下创建__init__.py与核心模块core.py。__init__.py可留空或定义包版本,core.py编写基础函数如def add(a, b): return a + b。随后在项目根目录创建pyproject.toml,使用现代构建系统配置项目元数据。例如采用setuptools时,需声明[build-system]依赖,并在[project]中定义名称、版本与依赖项。关键配置在于[tool.setuptools.packages.find],设置where = ["src"]以指示构建工具从src目录发现包。完成配置后,可通过pip install -e .进行可编辑安装,此时Python会将src/myapp映射到虚拟环境的site-packages中,确保开发期代码修改实时生效,同时保持目录结构的物理隔离。

配置测试导入与运行方式
在src布局下,测试文件必须通过绝对包路径导入源码,例如在tests/test_core.py中直接编写from myapp.core import add。由于源码位于src子目录而非当前工作目录,若未安装项目,Python将无法解析该导入。因此,运行测试前需确保项目已通过pip install -e .安装至当前虚拟环境,或依赖pytest的自动发现机制配合正确的PYTHONPATH。推荐做法是在项目根目录直接执行pytest,此时pytest会读取已安装的包路径并正确加载模块。若出现ImportError,通常是因为未激活虚拟环境或未执行可编辑安装。为避免手动配置环境变量,可在pyproject.toml中配置[tool.pytest.ini_options],设置testpaths = ["tests"],并依赖构建工具处理路径映射,从而保证开发环境与测试执行环境的一致性。

验证打包安装并排查常见路径问题
项目配置完成后,需验证打包边界是否符合预期。执行python -m build生成wheel文件后,可使用unzip -l dist/*.whl检查归档内容,确认仅包含src/myapp下的源码文件,而tests目录与开发配置文件均被排除。若安装后运行测试报ModuleNotFoundError: No module named 'myapp',通常由以下原因导致:一是虚拟环境未正确激活,导致site-packages路径未生效;二是pyproject.toml中packages.find的where参数配置错误,使构建工具未能正确识别src目录。排查时,可执行python -c "import sys; print(sys.path)"检查路径优先级,或使用pip show myapp确认安装位置。对于CI环境,建议在流水线中显式执行pip install -e .[dev]并清理缓存,确保测试依赖与运行环境严格对齐,从而消除本地与服务器之间的路径差异。
