从.py文件到PyPI:手把手教你打包发布自己的Python工具包
从.py文件到PyPI手把手教你打包发布自己的Python工具包当你写出一组好用的数据清洗函数或是开发了一个解决特定问题的Python脚本时是否想过让更多人能轻松使用你的代码将零散的.py文件转化为可通过pip install安装的标准Python包不仅能提升代码的复用性更是迈向开源贡献的第一步。本文将带你完整走通从代码到发布的全流程涵盖现代Python打包的最佳实践。1. 项目结构与基础配置一个标准的Python包远不止是几个.py文件的集合。合理的项目结构不仅能确保顺利打包还能为后续维护和功能扩展打下基础。以下是推荐的项目骨架my_package/ ├── src/ │ └── my_package/ │ ├── __init__.py │ ├── core.py │ └── utils.py ├── tests/ │ ├── test_core.py │ └── test_utils.py ├── pyproject.toml ├── setup.cfg ├── LICENSE └── README.md关键文件说明__init__.py标识目录为Python包可以是空文件也可包含包初始化代码pyproject.toml声明构建系统要求现代Python打包的核心配置文件setup.cfg静态配置元数据替代传统的setup.py提示将代码放在src目录下能避免常见的可编辑安装导致的导入问题这是Python打包专家们推荐的实践。2. 现代打包配置详解2.1 pyproject.toml配置这是PEP 518引入的配置文件指定了构建系统所需的环境[build-system] requires [setuptools61.0, wheel] build-backend setuptools.build_meta2.2 setup.cfg元数据替代传统的setup.py使用静态配置更安全可靠[metadata] name my-package version 0.1.0 author Your Name author_email your.emailexample.com description A short description long_description file: README.md long_description_content_type text/markdown url https://github.com/yourusername/my-package classifiers Development Status :: 3 - Alpha Intended Audience :: Developers License :: OSI Approved :: MIT License Programming Language :: Python :: 3 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 [options] package_dir src packages find: python_requires 3.8 install_requires numpy1.20 pandas1.3 [options.packages.find] where src3. 高级打包技巧3.1 包含非Python文件如需打包数据文件、模板等静态资源需添加[options.package_data] my_package *.json templates/*.html data/*.csv3.2 入口点与命令行工具将包中的函数暴露为命令行工具[options.entry_points] console_scripts my-tool my_package.cli:main这会让安装包后自动生成my-tool命令直接调用my_package/cli.py中的main函数。4. 构建与发布流程4.1 本地构建安装构建工具并生成分发文件pip install build python -m build这会在dist目录生成.whl和.tar.gz文件分别是wheel和sdist格式的分发包。4.2 测试发布先发布到TestPyPI进行验证pip install twine twine upload --repository testpypi dist/*测试安装pip install --index-url https://test.pypi.org/simple/ my-package4.3 正式发布确保测试无误后发布到官方PyPItwine upload dist/*发布后任何人都可以通过pip install your-package来安装你的工具了。5. 维护与版本管理良好的版本控制策略能让用户放心使用你的包。遵循语义化版本控制(SemVer)MAJOR不兼容的API修改MINOR向下兼容的功能新增PATCH向下兼容的问题修正每次发布新版本前记得更新setup.cfg中的版本号更新CHANGELOG.md记录变更打上Git标签git tag v1.0.0推送标签到远程git push origin --tags6. 提升包的质量要让你的包更专业建议添加以下内容完善的单元测试pytest代码风格检查flake8/black类型注解mypyCI/CD流水线GitHub Actions文档字符串与API文档Sphinx一个典型的测试文件示例from my_package.core import clean_data import pandas as pd import pytest def test_clean_data(): input_df pd.DataFrame({A: [1, 2, None], B: [x, y, z]}) result clean_data(input_df) assert not result.isnull().any().any() assert len(result) 37. 处理依赖关系精明的依赖管理能减少用户安装时的冲突必需依赖放在install_requires开发依赖放在requirements-dev.txt可选依赖使用extras_require[options.extras_require] test pytest6.0 pytest-cov2.0 dev black21.0 flake83.9用户可按需安装pip install my-package[test,dev]在实际项目中我发现过度依赖第三方包会增加维护负担。一个经验法则是只有当某个功能确实复杂到不值得自己实现时才引入外部依赖。曾经为了一个简单的配置文件解析功能引入了一个大型库结果后续版本兼容性问题耗费了大量调试时间。