名称: python-packaging 描述: 配置Python包的元数据、setup.py和pyproject.toml,使用UV或setuptools进行分发。适用于设置Python包、配置构建系统或准备项目发布到PyPI。
Python打包
配置Python包的元数据和构建配置以进行分发。
快速开始
创建pyproject.toml,使用UV或setuptools配置进行包分发。
说明
选择构建系统
使用UV与pyproject.toml(推荐)当:
- 开始新项目
- 希望快速、现代化的工具
- 需要依赖管理+打包
- 为PyPI构建库
- 希望符合PEP 621标准
使用setuptools(pyproject.toml + setup.py)当:
- 维护现有项目
- 需要与旧工具兼容
- 需要自定义构建步骤
- 复杂C扩展
使用setuptools(仅pyproject.toml)当:
- 现代setuptools-only方法
- 无自定义构建逻辑
- 希望声明式配置
- 符合PEP 621标准
UV配置(推荐)
使用UV创建pyproject.toml(PEP 621标准):
[project]
name = "my-package"
version = "0.1.0"
description = "Package description"
readme = "README.md"
requires-python = ">=3.9"
license = {text = "MIT"}
authors = [
{name = "Your Name", email = "you@example.com"}
]
keywords = ["keyword1", "keyword2"]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]
dependencies = [
"requests>=2.28.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
"mypy>=1.0.0",
]
[project.scripts]
my-cli = "my_package.cli:main"
[project.urls]
Homepage = "https://github.com/username/my-package"
Repository = "https://github.com/username/my-package"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
关键字段:
name: 包名称(使用连字符,导入时将转换为下划线)version: 语义版本控制(MAJOR.MINOR.PATCH)requires-python: Python版本约束dependencies: 运行时依赖,带版本约束optional-dependencies: 开发和可选依赖scripts: 控制台脚本入口点
版本约束:
>=2.28.0,<3.0.0: 兼容版本~=2.28.0: >=2.28.0, <2.29.0(补丁更新)>=2.28.0: 最低版本==2.28.0: 精确版本
Setuptools配置(现代)
使用setuptools创建pyproject.toml(PEP 621):
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "my-package"
version = "0.1.0"
description = "Package description"
readme = "README.md"
requires-python = ">=3.9"
license = {text = "MIT"}
authors = [
{name = "Your Name", email = "you@example.com"}
]
keywords = ["keyword1", "keyword2"]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
]
dependencies = [
"requests>=2.28.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
"mypy>=1.0.0",
]
[project.scripts]
my-cli = "my_package.cli:main"
[project.urls]
Homepage = "https://github.com/username/my-package"
Repository = "https://github.com/username/my-package"
Setuptools配置(传统)
为需要自定义构建逻辑的项目创建setup.py:
from setuptools import setup, find_packages
setup(
name="my-package",
version="0.1.0",
description="Package description",
long_description=open("README.md").read(),
long_description_content_type="text/markdown",
author="Your Name",
author_email="you@example.com",
url="https://github.com/username/my-package",
packages=find_packages(where="src"),
package_dir={"": "src"},
python_requires=">=3.9",
install_requires=[
"requests>=2.28.0",
],
extras_require={
"dev": [
"pytest>=7.0.0",
"black>=23.0.0",
"mypy>=1.0.0",
],
},
entry_points={
"console_scripts": [
"my-cli=my_package.cli:main",
],
},
classifiers=[
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
],
)
- 自定义构建步骤(编译C扩展)
- 从git标签动态版本
- 复杂包发现
- 条件依赖
包结构
扁平布局:
my-package/
├── my_package/
│ ├── __init__.py
│ └── module.py
├── tests/
├── pyproject.toml
└── README.md
Src布局(推荐用于库):
my-package/
├── src/
│ └── my_package/
│ ├── __init__.py
│ └── module.py
├── tests/
├── pyproject.toml
└── README.md
对于src布局,配置包发现:
UV/Hatchling(pyproject.toml):
[tool.hatch.build.targets.wheel]
packages = ["src/my_package"]
Setuptools(pyproject.toml):
[tool.setuptools.packages.find]
where = ["src"]
Setuptools(setup.py):
packages=find_packages(where="src"),
package_dir={"": "src"},
版本管理
静态版本在pyproject.toml中:
[project]
version = "0.1.0"
从文件动态版本:
[project]
dynamic = ["version"]
[tool.setuptools.dynamic]
version = {attr = "my_package.__version__"}
然后在src/my_package/__init__.py中:
__version__ = "0.1.0"
从git标签动态版本(需要setup.py):
from setuptools import setup
from setuptools_scm import get_version
setup(
use_scm_version=True,
setup_requires=["setuptools_scm"],
)
入口点和脚本
控制台脚本创建命令行工具:
[project.scripts]
my-cli = "my_package.cli:main"
another-tool = "my_package.tools:run"
这创建调用指定函数的可执行文件。
入口点函数:
# my_package/cli.py
def main():
print("Hello from my-cli!")
if __name__ == "__main__":
main()
包含数据文件
包含包数据:
[tool.setuptools.package-data]
my_package = ["data/*.json", "templates/*.html"]
包含非包文件:
创建MANIFEST.in:
include README.md
include LICENSE
recursive-include src/my_package/data *
分类器
使用PyPI分类器分类您的包:
classifiers = [
# 开发状态
"Development Status :: 3 - Alpha",
"Development Status :: 4 - Beta",
"Development Status :: 5 - Production/Stable",
# 受众
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
# 许可证
"License :: OSI Approved :: MIT License",
# Python版本
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
# 主题
"Topic :: Software Development :: Libraries",
"Topic :: Internet :: WWW/HTTP",
]
完整列表:https://pypi.org/classifiers/
构建和发布
使用UV(推荐):
# 构建分发
uv build
# 发布到PyPI
uv publish
# 或使用twine
uv build
twine upload dist/*
使用setuptools:
# 安装构建工具
pip install build twine
# 构建分发
python -m build
# 发布到PyPI
twine upload dist/*
测试安装
发布前本地测试您的包:
# 使用UV在可编辑模式安装
uv pip install -e .
# 或使用pip
pip install -e .
# 测试包
python -c "import my_package; print(my_package.__version__)"
# 测试控制台脚本
my-cli --help
常见模式
多包项目
对于具有多个包的项目:
[tool.hatch.build.targets.wheel]
packages = ["src/package1", "src/package2"]
可选依赖
分组可选功能:
[project.optional-dependencies]
dev = ["pytest", "black", "mypy"]
docs = ["sphinx", "sphinx-rtd-theme"]
aws = ["boto3"]
all = ["pytest", "black", "mypy", "sphinx", "boto3"]
安装:pip install my-package[dev] 或 pip install my-package[all]
平台特定依赖
[project]
dependencies = [
"requests",
"pywin32; platform_system=='Windows'",
"python-daemon; platform_system=='Linux'",
]
验证
发布前验证:
-
包成功构建:
uv build # 或 python -m build -
元数据正确:
twine check dist/* -
安装工作:
uv pip install dist/*.whl -
入口点工作:
my-cli --version -
导入工作:
import my_package print(my_package.__version__)
故障排除
安装后找不到包:
- 检查包名称与导入名称(连字符vs下划线)
- 验证包发现配置
- 确保包目录中存在
__init__.py
入口点不工作:
- 验证函数签名(应无参数或使用argparse)
- 检查入口点语法:
"script-name = "package.module:function" - 更改后重新安装包
数据文件未包含:
- 添加到pyproject.toml中的
package-data - 或创建MANIFEST.in
- 验证:
python -m tarfile -l dist/*.tar.gz
版本冲突:
- 使用兼容版本约束(
>=,<语法) - 测试不同依赖版本
- UV自动为可重复性创建锁文件