保姆级教程:用setuptools和twine把你的Python包发布到PyPI(附避坑指南)

张开发
2026/4/19 16:21:40 15 分钟阅读

分享文章

保姆级教程:用setuptools和twine把你的Python包发布到PyPI(附避坑指南)
从零到发布Python包打包与PyPI上传全流程实战指南第一次将自己的Python代码打包并分享给全世界开发者这种成就感无与伦比。但当你真正尝试时可能会在setup.py配置、twine上传等环节遇到各种坑。本文将用最直白的语言带你完整走通整个流程。1. 项目结构与基础准备1.1 创建标准的Python包结构一个规范的Python包至少需要包含以下结构my_awesome_package/ ├── my_awesome_package/ │ ├── __init__.py │ └── your_code.py ├── setup.py ├── README.md └── LICENSE其中__init__.py文件的作用标识这是一个Python包可以包含包的初始化代码控制from package import *的行为提示即使暂时不需要初始化代码也必须保留空的__init__.py文件1.2 必须的元数据文件LICENSE文件示例MIT许可证Copyright (c) [year] [fullname] Permission is hereby granted... [标准MIT许可证内容]README.md建议包含项目简介安装方法快速使用示例贡献指南联系方式2. 深度配置setup.py2.1 基础配置模板from setuptools import setup, find_packages with open(README.md, r, encodingutf-8) as f: long_description f.read() setup( nameyour-package-name, version0.1.0, authorYour Name, author_emailyour.emailexample.com, descriptionOne-line description, long_descriptionlong_description, long_description_content_typetext/markdown, urlhttps://github.com/yourusername/your-repo, packagesfind_packages(), classifiers[ Programming Language :: Python :: 3, License :: OSI Approved :: MIT License, Operating System :: OS Independent, ], python_requires3.6, )2.2 高级配置项解析依赖管理install_requires[ requests2.25.1, numpy1.20.0, ],包含数据文件package_data{ my_package: [data/*.json], },入口点配置创建命令行工具entry_points{ console_scripts: [ my-commandmy_package.module:main_func, ], },3. 打包与本地测试3.1 生成分发文件安装必要工具pip install --upgrade setuptools wheel生成打包文件python setup.py sdist bdist_wheel成功后会生成dist目录包含.tar.gz源码包.whl构建好的wheel包3.2 本地安装测试pip install ./dist/your_package-0.1.0-py3-none-any.whl测试要点能否正常导入所有功能是否可用命令行工具如果有是否工作4. PyPI上传全流程4.1 注册PyPI账号访问pypi.org注册账号在账号设置中生成API Token记住Token值只会显示一次4.2 使用twine上传安装twinepip install --upgrade twine上传到测试环境推荐先测试twine upload --repository testpypi dist/*正式上传到PyPItwine upload dist/*注意上传时用户名填__token__密码填你的API Token4.3 常见上传问题解决认证失败检查Token是否复制完整确认使用的是PyPI Token而不是TestPyPI的版本冲突每次上传必须更新版本号遵循语义化版本规范MAJOR.MINOR.PATCH网络问题尝试使用--verbose参数查看详细错误国内用户可尝试配置镜像源5. 发布后的维护与更新5.1 版本更新流程修改setup.py中的版本号重新生成分发文件上传新版本到PyPI版本号规范建议0.1.0 初始版本0.1.1 修复bug0.2.0 新增功能但不破坏兼容性1.0.0 稳定生产版本5.2 管理PyPI项目在PyPI项目页面可以查看下载统计管理项目描述删除错误版本添加维护者5.3 用户反馈处理建议在README中明确问题报告渠道GitHub Issues等预期响应时间贡献指南6. 高级技巧与最佳实践6.1 多环境测试使用tox自动化测试[tox] envlist py36, py37, py38, py39 [testenv] deps pytest commands pytest tests/6.2 自动化发布使用GitHub Actions自动发布name: Publish Python Package on: release: types: [created] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkoutv2 - name: Set up Python uses: actions/setup-pythonv2 - name: Install dependencies run: | python -m pip install --upgrade pip pip install setuptools wheel twine - name: Build package run: python setup.py sdist bdist_wheel - name: Publish package env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} run: twine upload dist/*6.3 文档与示例推荐使用Sphinx生成文档pip install sphinx sphinx-quickstart文档应该包括详细API参考教程和示例变更日志7. 安全与法律注意事项7.1 许可证选择常见开源许可证对比许可证允许商用要求署名要求开源专利授权MIT是是否否Apache是是否是GPL是是是否7.2 敏感信息检查确保包中不包含个人隐私信息硬编码的密码/密钥版权受限的内容可以使用工具扫描pip install bandit bandit -r your_package/8. 提升包的质量与影响力8.1 编写良好的测试测试覆盖率建议核心功能100%覆盖整体不低于80%使用pytest-cov测量pip install pytest pytest-cov pytest --covyour_package tests/8.2 性能优化技巧使用__slots__减少内存占用延迟加载重型依赖提供预编译的wheel包8.3 社区推广有效推广渠道Python邮件列表相关领域的论坛GitHub展示技术博客文章9. 疑难问题解决方案9.1 依赖冲突处理使用pip check检测冲突pip install your-package pip check解决方案放宽依赖版本要求提供可选依赖组使用虚拟环境隔离9.2 跨平台兼容性常见问题路径分隔符差异编码问题系统依赖差异测试建议使用CI测试多平台明确声明支持平台提供替代实现9.3 大型项目分包策略对于复杂项目my_project/ ├── core/ │ ├── __init__.py │ └── ... ├── extensions/ │ ├── __init__.py │ └── ... └── utils/ ├── __init__.py └── ...使用namespace packagessetup( ... packagesfind_namespace_packages(include[my_project.*]), )10. 持续维护与迭代建立有效的维护流程使用Git管理版本制定明确的发布周期建立问题跟踪系统定期更新依赖版本弃用策略提前公告弃用计划提供迁移指南保留足够过渡期在项目根目录添加.python-version文件可以帮助开发者使用正确的Python版本3.8.6

更多文章