实战指南 | 从零到一:构建并发布你的首个 Python 包到 PyPI
1. 为什么需要打包Python项目?
当你写了一个实用的Python工具或库,想让其他人也能方便地使用时,最直接的方式就是把它发布到PyPI(Python Package Index)上。PyPI是Python官方的包托管平台,全球开发者都可以通过pip install 你的包名来安装你的作品。
想象一下这个场景:你写了一个自动整理电脑桌面文件的脚本,同事看到后也想用。如果直接发.py文件给对方,他需要手动下载依赖、处理路径问题。但如果你把代码打包上传到PyPI,对方只需要一行命令就能安装使用——这才是真正的"程序员友好"。
2. 项目结构规划
一个标准的Python包目录结构应该像这样:
your_package/ ├── pyproject.toml # 构建配置文件(核心) ├── src/ # 源码目录 │ └── your_package/ # 你的包名 │ ├── __init__.py │ └── module.py ├── tests/ # 测试代码 ├── LICENSE # 开源许可证 └── README.md # 项目说明这里有个新手常踩的坑:很多人喜欢把代码直接放在项目根目录,但这会导致后续打包和导入出现问题。正确的做法是使用src布局,所有代码放在src/包名下。我刚开始时就犯过这个错误,调试了半天导入失败的问题。
3. 编写核心配置文件
pyproject.toml是现代Python打包的核心配置文件,它取代了旧的setup.py。下面是一个完整的配置示例:
[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "example_package_你的用户名" # 必须是唯一的 version = "0.1.0" authors = [ {name = "你的名字", email = "你的邮箱"}, ] description = "一个简短的描述" readme = "README.md" requires-python = ">=3.8" classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", ] [project.urls] Homepage = "https://github.com/yourname/yourpackage"几个关键点说明:
name必须全局唯一,建议加上你的用户名version遵循语义化版本规范(MAJOR.MINOR.PATCH)classifiers是PyPI的分类标签,完整的列表可以在PyPI官网找到
4. 处理依赖和许可证
4.1 依赖管理
如果你的包依赖其他库,在pyproject.toml中添加:
dependencies = [ "requests>=2.25.0", "numpy<2.0.0", # 可以指定版本范围 ]建议使用宽松的版本范围(如>=2.25.0而不是==2.25.0),避免与其他包的依赖冲突。
4.2 选择开源许可证
常见的许可证有:
- MIT:最宽松,允许任意使用
- Apache 2.0:包含专利授权条款
- GPL:要求衍生作品也必须开源
创建LICENSE文件,复制你选择的许可证文本。MIT许可证示例:
Copyright (c) 2023 你的名字 Permission is hereby granted... [此处省略完整许可证文本]5. 构建包
5.1 安装构建工具
pip install --upgrade build5.2 执行构建
在项目根目录运行:
python -m build这会生成dist目录,包含两个文件:
.tar.gz:源码分发版.whl:构建好的wheel文件
第一次构建时我遇到了ERROR: Unknown distribution option: 'long_description_content_type'错误,后来发现是因为pyproject.toml格式不对。建议复制上面的模板避免这类问题。
6. 上传到PyPI
6.1 注册PyPI账号
- 访问 pypi.org 注册账号
- 在账号设置中创建API Token(作用域选整个账户)
6.2 安装上传工具
pip install --upgrade twine6.3 创建配置文件
在用户目录下创建.pypirc(Windows在C:\Users\你的用户名\):
[pypi] username = __token__ password = pypi-你的API令牌6.4 上传包
twine upload dist/*上传成功后你会看到类似这样的输出:
Uploading example_package-0.1.0-py3-none-any.whl 100%|█████████████████████| 5.25k/5.25k [00:01<00:00, 3.05kB/s]7. 验证和版本更新
7.1 安装测试
pip install example-package-你的用户名7.2 版本更新流程
- 修改代码后,更新
pyproject.toml中的version - 重新构建:
python -m build - 上传新版本:
twine upload dist/*
记住永远不要重复上传同一个版本号的文件,PyPI不允许覆盖已发布的版本。如果上传出错,必须增加版本号重新发布。
8. 高级技巧和常见问题
8.1 包含非Python文件
如果需要打包数据文件(如CSV、图片等),创建MANIFEST.in文件:
include src/your_package/data/*.csv8.2 测试PyPI
正式发布前,可以先用测试平台验证:
twine upload --repository testpypi dist/*测试PyPI地址:https://test.pypi.org
8.3 常见错误解决
- 403 Forbidden:检查API Token是否正确
- 400 File already exists:增加版本号重新构建
- 导入错误:确保
__init__.py文件存在
我第一次上传时因为网络问题失败了三次,后来发现用国内镜像源可能会出现问题,建议直接连接PyPI主站。
