打包 Python 项目

本教程将带你一步步打包一个简单的 Python 项目。你将学习如何添加必要的文件和目录结构来创建一个可发布的包,如何构建这个包,并将其上传到 Python Package Index (PyPI)。

部分命令需要较新版本的 pip,因此请先确保你已安装最新版:

python 复制代码
# Windows 用户
python -m pip install --upgrade pip

一个简单的项目

本教程使用一个名为 example_package_YOUR_USERNAME_HERE 的示例项目。

例如,如果你的用户名是 me,那么包名就是 example_package_me。这样可以确保你的包名是唯一的,不会与其他学习者上传的包冲突。

我们建议你先完整地按照本教程操作一遍这个示例项目,之后再尝试打包自己的项目。

在本地创建如下目录结构:

复制代码
packaging_tutorial/
└── src/
    └── example_package_YOUR_USERNAME_HERE/
        ├── __init__.py
        └── example.py

📌 说明:包含 Python 模块的目录名称应与项目名一致。这不仅简化了配置,也更便于用户理解。

  • init.py 文件的存在使得该目录能被当作一个标准的 Python 包导入(即使它是空的)。
  • example.py 是包中的一个模块,用于存放你的核心逻辑(如函数、类、常量等)。打开它并写入以下内容:
python 复制代码
def add_one(number):
    return number + 1

创建好上述结构后,请确保后续所有命令都在 packaging_tutorial/ 目录下执行。

添加打包所需的文件

接下来,你需要添加一些用于准备发布项目的文件。完成后,项目结构应如下所示:

python 复制代码
packaging_tutorial/
├── LICENSE
├── pyproject.toml
├── README.md
├── src/
│   └── example_package_YOUR_USERNAME_HERE/
│       ├── __init__.py
│       └── example.py
└── tests/
创建测试目录

tests/ 是预留的测试文件目录,目前可以留空。

选择构建后端(Build Backend)

像 pip 和 build 这样的工具本身并不负责将源代码打包成分发格式(例如 wheel 文件),这项工作由 构建后端(build backend) 完成。

构建后端决定了你的项目如何声明元数据(如包名、版本、作者、PyPI 上显示的信息等)以及哪些文件需要被打包。不同的后端功能略有差异(例如是否支持编译 C 扩展模块),你可以根据需求选择合适的工具。

常见的构建后端包括:

  • Hatchling(本教程默认使用)
  • Setuptools
  • Flit
  • PDM
  • uv-build

⚠️ 注意:某些构建工具(如 PDM、Hatch)还提供了额外功能,比如项目初始化、版本管理、上传等。但本教程仅使用独立的、单一用途的工具(如 build 和 twine)。

构建后端的选择通过 pyproject.toml 文件中的 [build-system] 部分指定。以下是几个常见后端的配置示例:

Hatchling(推荐)

python 复制代码
[build-system]
requires = ["hatchling >= 1.26"]
build-backend = "hatchling.build"

Setuptools

python 复制代码
[build-system]
requires = ["setuptools >= 61.0", "wheel"]
build-backend = "setuptools.build_meta"

🔍 说明:

  • requires 列出了构建包所必需的依赖项(通常包括构建后端本身)。前端工具(如 build)会在隔离环境中自动安装这些依赖。
  • build-backend 指定了用于执行构建的 Python 对象路径。

这两个字段通常由你选择的构建工具文档提供,一般无需手动修改。

配置项目元数据

打开 pyproject.toml,填入以下内容。记得将包名中的 YOUR_USERNAME_HERE 替换为你的实际用户名,以确保唯一性:

toml 复制代码
[project]
name = "example_package_your_username_here"
version = "0.0.1"
authors = [
  { name = "Example Author", email = "author@example.com" },
]
description = "一个简单的示例包"
readme = "README.md"
requires-python = ">=3.9"
classifiers = [
    "Programming Language :: Python :: 3",
    "Operating System :: OS Independent",
]
license = { text = "MIT" }
license-files = ["LICENSE"]

[project.urls]
Homepage = "https://github.com/pypa/sampleproject"
Issues = "https://github.com/pypa/sampleproject/issues"

字段说明:

  • name:包的分发名称。只能包含字母、数字、.、_、-,且不能与 PyPI 上已有包重名。
  • version:包的版本号(某些后端支持从 Git 标签或文件中自动读取)。
  • authors:作者信息,可包含姓名和邮箱。也可用相同格式列出维护者(maintainers)。
  • description:简短的一句话描述。
  • readme:指向 README 文件的路径,内容会显示在 PyPI 项目页面上。
  • requires-python:指定项目兼容的 Python 版本范围。pip 会据此选择合适的包版本。
  • classifiers:提供额外元数据,帮助用户和索引系统理解你的包。至少应包含 Python 版本和操作系统兼容性。完整分类列表见 PyPI 分类器页面
  • license:使用 SPDX 许可证标识符(如 "MIT")。
  • license-files:许可证文件的路径(相对于 pyproject.toml 所在目录)。注意:原文中的 ["LICEN[CS]E*"] 是一种 glob 写法,但为了清晰和兼容性,建议直接写 ["LICENSE"]。
  • urls:可在 PyPI 页面上显示的额外链接,如源码、文档、问题追踪等。

更多字段(如 keywords、dependencies)可参考 pyproject.toml 官方指南。

编写 README.md

创建 README.md 文件,内容如下(可自行修改):

python 复制代码
# 示例包

这是一个简单的示例包。你可以使用 [GitHub 风格的 Markdown](https://guides.github.com/features/mastering-markdown/) 来撰写内容。

添加 LICENSE(许可证)

每个上传到 PyPI 的包都必须包含许可证,以告知用户他们可以如何使用你的代码。

推荐访问 choosealicense.com 选择合适的许可证。例如,选择 MIT 许可证,则 LICENSE 文件内容如下:

复制代码
Copyright (c) 2026 Your Name

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

✅ 大多数现代构建后端会自动将 LICENSE 文件包含进最终的分发包中,前提是它在 license-files 中正确声明。

生成分发包(Distribution Archives)

下一步是生成可上传到 PyPI 的分发包。这些包可以被 pip 安装。

首先确保已安装最新版的 build 工具:

python 复制代码
# Windows
python -m pip install --upgrade build

然后在 pyproject.toml 所在目录运行:

python 复制代码
# Windows
python -m build

成功后,会在 dist/ 目录下生成两个文件:

复制代码
dist/
├── example_package_your_username-0.0.1-py3-none-any.whl
└── example_package_your_username-0.0.1.tar.gz
  • .tar.gz 是 源码分发包(source distribution)
  • .whl 是 构建好的 wheel 包(built distribution)

📦 现代 pip 优先安装 wheel 包,若不可用则回退到源码包。建议始终同时提供源码包和适用于目标平台的 wheel 包。本例中包是纯 Python 且跨平台,因此只需一个 wheel。

上传到 PyPI

现在,将你的包上传到 TestPyPI(PyPI 的测试环境,专用于实验,不会影响正式索引)。

步骤 1:注册 TestPyPI 账号

前往 https://test.pypi.org/account/register/ 注册账号,并验证邮箱。

步骤 2:创建 API Token

登录后,进入 API Tokens 页面,创建一个作用域为 "Entire account" 的 Token。务必在关闭页面前复制保存------你之后无法再次查看明文 Token

步骤 3:使用 Twine 上传

安装 twine:

python 复制代码
# Windows
py -m pip install --upgrade twine

上传所有分发包:

python 复制代码
# Windows
py -m twine upload --repository testpypi dist/*

系统会提示你输入 API Token(格式如 pypi-xxxxx),粘贴即可(输入时不可见,请确保准确)。

成功后,你会看到类似输出:

复制代码
Uploading example_package_your_username_here-0.0.1-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.2/8.2 kB • 00:01 • ?
Uploading example_package_your_username_here-0.0.1.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.8/6.8 kB • 00:00 • ?

上传完成后,你的包将在 TestPyPI 上可见。

安装并测试你的包

使用 pip 从 TestPyPI 安装你的包进行验证:

python 复制代码
# Windows
py -m pip install --index-url https://test.pypi.org/simple/ --no-deps example-package-your-username

🔒 注意:

  • 使用 --index-url 指定 TestPyPI;
  • 使用 --no-deps 避免因 TestPyPI 缺少依赖而导致安装失败(虽然本例无依赖,但这是良好实践)。

安装成功后,启动 Python 并测试:

python 复制代码
from example_package_your_username import example
print(example.add_one(2))  # 输出:3

下一步

🎉 恭喜!你已经成功打包并发布了你的第一个 Python 项目!

接下来,你可以:

  • 将真实项目按此流程打包;
  • 添加单元测试(放入 tests/);
  • 配置 CI/CD 自动构建和发布;
  • 上传到正式 PyPI(需注册 pypi.org 账号)。

祝你打包顺利!✨🍰✨

参考文献

https://packaging.python.org/en/latest/tutorials/packaging-projects/

相关推荐
万行1 小时前
机器人系统SLAM讲解
开发语言·python·决策树·机器学习·机器人
我的xiaodoujiao1 小时前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 40--完善优化 Allure 测试报告显示内容
python·学习·测试工具·pytest
WinstonJQ1 小时前
AirSim无人机仿真入门(一):实现无人机的起飞与降落
python·机器人·游戏引擎·ue4·无人机
tjjucheng1 小时前
专业做小程序定制开发的厂家
python
Hello.Reader1 小时前
Flink DynamoDB Connector 用 Streams 做 CDC,用 BatchWriteItem 高吞吐写回
大数据·python·flink
gc_22992 小时前
学习python调用dmpython库获取达梦数据库模式信息的基本方式
python·dmpython
reasonsummer2 小时前
【教学类-130-01】20260118对称汉字剪纸28个
python
victory04312 小时前
minimind SFT失败原因排查和解决办法
人工智能·python·深度学习
曲幽2 小时前
Django入门指南:Python Web开发的“瑞士军刀”
python·django·flask·fastapi·web·pythonweb