PyPI 制品管理的基础概念
PyPI(Python Package Index)是 Python 生态中用于存储和分发开源软件包的官方仓库。管理 PyPI 制品包括包的构建、版本控制、上传及依赖管理。通过工具如 twine 和 setuptools,开发者可以将本地代码打包并发布到 PyPI 或私有仓库。
构建 Python 包
Python 包的构建依赖于 setup.py 或 pyproject.toml 文件定义元数据。以下是一个最小化的 setup.py 示例:
from setuptools import setup
setup(
name="example_package",
version="0.1",
author="Your Name",
description="A sample Python package",
packages=["example_package"],
install_requires=["requests>=2.25.0"],
)
使用 pyproject.toml 的现代配置方式:
[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"
[project]
name = "example_package"
version = "0.1"
authors = [{name = "Your Name"}]
dependencies = ["requests>=2.25.0"]
运行构建命令生成分发文件:
python setup.py sdist bdist_wheel # 传统方式
# 或使用现代工具
pip install build
python -m build
版本控制策略
遵循语义化版本(SemVer)规范(MAJOR.MINOR.PATCH):
MAJOR:破坏性变更时递增。MINOR:向后兼容的功能新增时递增。PATCH:向后兼容的问题修复时递增。
通过 __version__ 在代码中定义版本:
# example_package/__init__.py
__version__ = "0.1.0"
上传到 PyPI
使用 twine 上传制品至 PyPI:
- 注册 PyPI 账号并生成 API Token。
- 安装工具:
pip install twine
- 上传构建好的包:
twine upload dist/*
若需上传到私有仓库,在 ~/.pypirc 中配置:
[distutils]
index-servers =
private
[private]
repository = https://your.private.repo
username = your_username
password = your_token
依赖管理
在 setup.py 或 pyproject.toml 中声明依赖项。使用 pip 安装时自动解析:
pip install example_package
对于复杂依赖,可通过 requirements.txt 细化版本约束:
requests==2.28.1
numpy>=1.21.0
自动化发布流程
结合 CI/CD 工具(如 GitHub Actions)自动化构建和发布:
# .github/workflows/publish.yml
name: Publish to PyPI
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: pip install build twine
- run: python -m build
- run: twine upload dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
私有仓库管理
使用 devpi 或 Nexus Repository 搭建私有 PyPI 仓库。例如,通过 devpi 快速搭建本地测试环境:
pip install devpi-server
devpi-server --start
devpi use http://localhost:3141
devpi user -c testuser password=123
devpi login testuser --password=123
devpi index -c dev bases=root/pypi
安全与权限控制
- API Token:避免使用密码,优先采用 PyPI 的令牌机制。
- GPG 签名:为包添加数字签名提升安全性:
gpg --detach-sign -a dist/example_package-0.1.tar.gz
twine upload --sign dist/*
实战案例:发布一个 CLI 工具
假设有一个命令行工具 hadess-cli,结构如下:
hadess-cli/
├── hadess_cli/
│ ├── __init__.py
│ └── cli.py
├── setup.py
└── README.md
cli.py 内容:
import click
@click.command()
def greet():
click.echo("Hello from Hadess CLI!")
if __name__ == "__main__":
greet()
在 setup.py 中注册命令行入口点:
setup(
...,
entry_points={
"console_scripts": ["hadess-cli=hadess_cli.cli:greet"]
}
)
构建并发布后,用户可通过 pip install hadess-cli 安装,并直接运行 hadess-cli。
常见问题排查
- 上传失败:检查网络或令牌权限,确保包名唯一。
- 依赖冲突:使用
pip check验证依赖树是否完整。 - 版本覆盖:PyPI 不允许重复上传相同版本号的文件。
通过上述流程,开发者可以高效管理 Python 制品的全生命周期。
fcng5sjpybk8.feishu.cn/wiki/ZpGMwsGVfiA2iWkAwBlcey23n1f?from=from_copylink
fcng5sjpybk8.feishu.cn/wiki/ViYwwvNtbiracykUDXlcYy7znqh?from=from_copylink
fcng5sjpybk8.feishu.cn/wiki/YRmowxwWhi6jElk6L2RchsjynVe?from=from_copylink
fcng5sjpybk8.feishu.cn/wiki/IM6HwLckHiRpe1kwVKFcSOaCngf?from=from_copylink
fcng5sjpybk8.feishu.cn/wiki/GmOwwRo4qin2XUkOqdgcJhwenLe?from=from_copylink
2336

被折叠的 条评论
为什么被折叠?



