Python项目结构与打包工具实践
目录
1、前言
2、传统项目布局
3、src-layout(源布局)(推荐)
4、pyproject.toml配置
5、使用python -m build打包
5.1、安装打包工具
5.2、打包执行流程
5.3、打包产物说明
5.3.1. dist目录内容
5.3.2. egg-info元数据目录
5.4、项目目录结构建议
1、前言
在Python开发的早期年代,setup.py
文件是项目打包的首选方案。然而,随着Python社区的蓬勃发展和项目复杂性的日益增加,这一传统方式逐渐显现出其局限性:
-
配置繁琐复杂:
setup.py
作为一个可执行脚本,常常混杂着复杂的逻辑和条件判断,使得配置文件变得冗长且难以阅读。 -
可重复性问题频发:构建过程高度依赖于环境状态,这导致在不同的开发环境中难以保证构建结果的一致性。
-
维护成本高昂:项目的元数据与构建逻辑相互交织,使得
setup.py
文件变得难以长期维护和管理。
幸运的是,2020年PEP 517和PEP 518的提出为Python打包生态带来了革命性的变革。pyproject.toml
文件作为全新的配置文件格式,以其显著的优势迅速获得了开发者的青睐:
-
标准化配置:
pyproject.toml
采用TOML格式,这是一种更加简洁、易读的配置文件格式,使得项目配置变得更加直观和易于管理。 -
构建环境隔离:通过明确声明构建依赖项,
pyproject.toml
确保了构建过程的环境一致性,从而有效避免了因环境差异导致的构建问题。 -
完美兼容:
pyproject.toml
不仅支持传统的打包工具,还能与现代构建系统无缝对接,为开发者提供了更大的灵活性和便利性。
综上所述,pyproject.toml
文件的引入标志着Python打包方式的重要进步。它不仅解决了传统setup.py
方式中的诸多痛点,还为项目的构建、分发和维护带来了更加高效、可靠的解决方案。
在现代Python项目中通常使用pyproject.toml
文件来配置构建系统。关于项目的目录结构,尽管存在多种布局方式,但最为常见的布局有两种:传统的项目布局和src-layout(源布局)。下面将详细介绍这两种布局方式及其优缺点。
2、传统项目布局
目录结构示例:
my_project/
├── my_package/
│ ├── __init__.py
│ └── some_module.py
├── tests/
│ ├── __init__.py
│ └── test_some_module.py
├── README.md
├── requirements.txt
├── setup.py (可选,逐渐被pyproject.toml替代)
└── pyproject.toml (现代Python项目的标准配置文件)
特点:
-
源代码位置:项目的源代码(即包含
__init__.py
的目录)直接放置在项目根目录下。 -
测试代码:测试代码通常放置在
tests
目录下。 -
配置文件:
README.md
文件用于项目文档,requirements.txt
(或pyproject.toml
中的依赖声明)记录项目所需的依赖包及其版本号,setup.py
(可选)用于定义项目的安装方法(但逐渐被pyproject.toml
替代)。
实际项目用法:
-
在这种布局下,开发者可以直接在项目根目录下运行构建、测试等命令。
-
由于源代码直接放置在根目录下,可能会与项目文档、配置文件等混杂在一起,导致项目结构不够清晰。
3、src-layout(源布局)(推荐)
目录结构示例:
my_project/
├── src/ # 所有源代码都在这里
│ ├── my_package/
│ │ ├── __init__.py #
│ │ └── some_module.py
├── tests/ # 测试代码
│ ├── __init__.py
│ └── test_some_module.py
├── docs/ # 项目文档目录,存放Sphinx等生成的文档
├── scripts/ # 部署/运维脚本存放位置
├── data/ # 静态资源文件(如JSON/CSV)
├── .gitignore # Git忽略规则
├── LICENSE # 许可证
├── README.md # 许可证
├── requirements.txt # 许可证
└── pyproject.toml # 构建配置
特点:
-
源代码位置:项目的主要源代码被放置在
src
目录下,这有助于避免源码直接放在根目录下可能导致的全局命名空间污染问题。 -
测试代码:测试代码仍然放置在
tests
目录下。 -
配置文件:
README.md
、requirements.txt
和pyproject.toml
等文件的位置与传统布局相同。 -
__init__.py
文件:实际开发中建议始终保留该文件,即使内容为空,这有助于:-
明确标识Python包结构
-
为未来功能扩展预留空间
-
保持与旧版本兼容性
-
使用src布局的优点:
-
避免命名空间污染:通过将源代码放置在
src
目录下,可以避免项目包在安装时与全局Python环境中的其他包发生冲突。 -
更容易控制包结构:
src
布局使得开发者能够更精确地控制安装时的包结构,有助于保持项目的清晰和可维护性。 -
符合现代Python项目标准:随着
pyproject.toml
的普及,src
布局已成为现代Python项目的一种标准做法。
实际项目用法:
-
在这种布局下,开发者通常需要在构建命令中指定
src
目录作为源代码的根目录(例如,在使用Poetry等现代构建工具时)。 -
由于
src
布局提供了更清晰的项目结构,因此有助于提升项目的可读性和可维护性。
综上所述,传统项目布局和src-layout各有优缺点。对于新项目而言,建议采用src-layout以享受其带来的清晰项目结构和避免命名空间污染等好处。同时,无论采用哪种布局方式,都应充分利用pyproject.toml
文件来配置项目的构建系统和其他相关设置。
4、pyproject.toml配置
在日常项目开发中,可以使用PyCharm IDE自动化管理 pyproject.toml
文件,通过以下自动化机制显著简化了 pyproject.toml
的维护工作:
-
智能依赖管理
-
自动解析并可视化依赖关系图
-
版本冲突实时检测(通过波浪线提示)
-
一键更新依赖版本(Alt+Enter 快速修复)
-
动态配置同步
-
文件修改后自动更新项目结构
-
与虚拟环境实时联动(requirements 自动同步)
-
构建参数自动补全(输入时提示有效字段)
-
全生命周期支持
-
新建项目时自动生成合规模板
-
重构时自动更新受影响配置项
-
支持多构建系统(Setuptools/Poetry/Hatch 等)
典型工作流示例:
[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"
[project]
name = "my_package"
version = "0.1.0"
description = "我的Python包"
authors = [{name = "开发者姓名", email = "email@example.com"}]
weather_mcp_server项目pyproject.toml示例:
[project]
name = "weather-mcp-server"
version = "0.1.0"
description = "Add your description here"
requires-python = ">=3.11"
dependencies = ["dotenv>=0.9.9","mcp>=1.12.2","openai>=1.97.1",
]
authors = [{name = "爱编程的大叔", email = "416501600@qq.com"}]
5、使用python -m build打包
以下演示如何使用build命令打包weather_mcp_server项目,进入项目目录执行如下打包步骤:cd D:\python\mcp\weather_mcp_server
。
5.1、安装打包工具
-
推荐使用清华源加速安装:
-
执行命令:
uv pip install -i https://pypi.tuna.tsinghua.edu.cn/simple build twine
-
注意:当前清华源可能存在证书警告,建议验证连接安全性
-
其他推荐镜像源:
-
阿里云:
http://mirrors.aliyun.com/pypi/simple
-
中科大:
https://pypi.mirrors.ustc.edu.cn/simple
-
-
-
核心工具说明:
-
build
:Python官方推荐的打包工具 -
twine
:用于上传包到PyPI的工具
-
5.2、打包执行流程
# 执行打包命令
python -m build
打包成功后会打印如下信息:
adding 'mcp_server/__init__.py'
adding 'mcp_server/weather_server.py'
adding 'weather_mcp_server-0.1.0.dist-info/METADATA'
adding 'weather_mcp_server-0.1.0.dist-info/WHEEL'
adding 'weather_mcp_server-0.1.0.dist-info/top_level.txt'
adding 'weather_mcp_server-0.1.0.dist-info/RECORD'
removing build\bdist.win-amd64\wheel
Successfully built weather_mcp_server-0.1.0.tar.gz and weather_mcp_server-0.1.0-py3-none-any.whl
至此,weather_mcp_server项目打包成功。
5.3、打包产物说明
5.3.1. dist目录内容
打包完成后生成以下文件:
-
weather_mcp_server-0.1.0-py3-none-any.whl
:Wheel格式的二进制分发包 -
weather_mcp_server-0.1.0.tar.gz
:源码分发包
5.3.2. egg-info元数据目录
在src目录下生成的weather_mcp_server.egg-info
包含:
-
PKG-INFO:项目基本信息(名称/版本/作者等)
-
requires.txt:项目依赖清单
-
SOURCES.txt:打包包含的所有文件列表
-
top_level.txt:顶层包名称
-
dependency_links.txt:依赖链接信息
5.4、项目目录结构建议
典型Python打包项目应包含:
-
src/:核心源代码目录
-
tests/:单元测试代码
-
docs/:项目文档
-
pyproject.toml:构建配置文件
-
README.md:项目说明
注意:打包时会自动识别__init__.py
文件定义的包结构。
典型的 Python 项目结构