python-packaging
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePython Packaging
Python包打包与分发
Configure Python package metadata and build configuration for distribution.
配置用于分发的Python包元数据和构建配置。
Quick Start
快速开始
Create pyproject.toml with UV or setuptools configuration for package distribution.
创建包含UV或setuptools配置的pyproject.toml文件,用于包分发。
Instructions
操作指南
Choosing Build System
选择构建系统
Use UV with pyproject.toml (recommended) when:
- Starting new projects
- Want fast, modern tooling
- Need dependency management + packaging
- Building libraries for PyPI
- Want PEP 621 compliance
Use setuptools (pyproject.toml + setup.py) when:
- Maintaining existing projects
- Need compatibility with older tools
- Require custom build steps
- Complex C extensions
Use setuptools (pyproject.toml only) when:
- Modern setuptools-only approach
- No custom build logic
- Want declarative configuration
- PEP 621 compliance
推荐在以下场景使用UV + pyproject.toml:
- 启动新项目
- 想要快速、现代化的工具链
- 需要依赖管理 + 包打包能力
- 为PyPI构建库
- 希望符合PEP 621标准
在以下场景使用setuptools(pyproject.toml + setup.py):
- 维护现有项目
- 需要与旧工具兼容
- 自定义构建步骤
- 复杂的C扩展
在以下场景使用setuptools(仅pyproject.toml):
- 现代化的纯setuptools方案
- 无需自定义构建逻辑
- 希望使用声明式配置
- 符合PEP 621标准
UV Configuration (Recommended)
UV配置(推荐)
Create with UV (PEP 621 standard):
pyproject.tomltoml
[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"Key fields:
- : Package name (use hyphens, will be converted to underscores for import)
name - : Semantic versioning (MAJOR.MINOR.PATCH)
version - : Python version constraint
requires-python - : Runtime dependencies with version constraints
dependencies - : Development and optional dependencies
optional-dependencies - : Console script entry points
scripts
Version constraints:
- : Compatible versions
>=2.28.0,<3.0.0 - : >=2.28.0, <2.29.0 (patch updates)
~=2.28.0 - : Minimum version
>=2.28.0 - : Exact version
==2.28.0
创建符合PEP 621标准的UV配置文件:
pyproject.tomltoml
[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 - :Python版本约束
requires-python - :运行时依赖及版本约束
dependencies - :开发依赖和可选依赖
optional-dependencies - :控制台脚本入口点
scripts
版本约束说明:
- :兼容版本范围
>=2.28.0,<3.0.0 - :>=2.28.0 且 <2.29.0(仅补丁版本更新)
~=2.28.0 - :最低版本要求
>=2.28.0 - :精确版本要求
==2.28.0
Setuptools Configuration (Modern)
Setuptools配置(现代化方案)
Create with setuptools (PEP 621):
pyproject.tomltoml
[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"创建符合PEP 621标准的setuptools配置文件:
pyproject.tomltoml
[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 Configuration (Legacy)
Setuptools配置(传统方案)
Create for projects requiring custom build logic:
setup.pypython
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",
],
)When to use setup.py:
- Custom build steps (compiling C extensions)
- Dynamic version from git tags
- Complex package discovery
- Conditional dependencies
为需要自定义构建逻辑的项目创建:
setup.pypython
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",
],
)何时使用setup.py:
- 自定义构建步骤(如编译C扩展)
- 从Git标签动态获取版本号
- 复杂的包发现逻辑
- 条件依赖
Package Structure
包结构
Flat layout:
my-package/
├── my_package/
│ ├── __init__.py
│ └── module.py
├── tests/
├── pyproject.toml
└── README.mdSrc layout (recommended for libraries):
my-package/
├── src/
│ └── my_package/
│ ├── __init__.py
│ └── module.py
├── tests/
├── pyproject.toml
└── README.mdFor src layout, configure package discovery:
UV/Hatchling (pyproject.toml):
toml
[tool.hatch.build.targets.wheel]
packages = ["src/my_package"]Setuptools (pyproject.toml):
toml
[tool.setuptools.packages.find]
where = ["src"]Setuptools (setup.py):
python
packages=find_packages(where="src"),
package_dir={"": "src"},扁平化结构:
my-package/
├── my_package/
│ ├── __init__.py
│ └── module.py
├── tests/
├── pyproject.toml
└── README.mdSrc结构(推荐用于库项目):
my-package/
├── src/
│ └── my_package/
│ ├── __init__.py
│ └── module.py
├── tests/
├── pyproject.toml
└── README.md对于Src结构,需配置包发现规则:
UV/Hatchling(pyproject.toml):
toml
[tool.hatch.build.targets.wheel]
packages = ["src/my_package"]Setuptools(pyproject.toml):
toml
[tool.setuptools.packages.find]
where = ["src"]Setuptools(setup.py):
python
packages=find_packages(where="src"),
package_dir={"": "src"},Version Management
版本管理
Static version in pyproject.toml:
toml
[project]
version = "0.1.0"Dynamic version from file:
toml
[project]
dynamic = ["version"]
[tool.setuptools.dynamic]
version = {attr = "my_package.__version__"}Then in :
src/my_package/__init__.pypython
__version__ = "0.1.0"Dynamic version from git tags (requires setup.py):
python
from setuptools import setup
from setuptools_scm import get_version
setup(
use_scm_version=True,
setup_requires=["setuptools_scm"],
)在pyproject.toml中设置静态版本号:
toml
[project]
version = "0.1.0"从文件中动态获取版本号:
toml
[project]
dynamic = ["version"]
[tool.setuptools.dynamic]
version = {attr = "my_package.__version__"}然后在中添加:
src/my_package/__init__.pypython
__version__ = "0.1.0"从Git标签动态获取版本号(需使用setup.py):
python
from setuptools import setup
from setuptools_scm import get_version
setup(
use_scm_version=True,
setup_requires=["setuptools_scm"],
)Entry Points and Scripts
入口点与脚本
Console scripts create command-line tools:
toml
[project.scripts]
my-cli = "my_package.cli:main"
another-tool = "my_package.tools:run"This creates executables that call the specified functions.
Entry point function:
python
undefined控制台脚本用于创建命令行工具:
toml
[project.scripts]
my-cli = "my_package.cli:main"
another-tool = "my_package.tools:run"这会生成可执行文件,调用指定的函数。
入口点函数示例:
python
undefinedmy_package/cli.py
my_package/cli.py
def main():
print("Hello from my-cli!")
if name == "main":
main()
undefineddef main():
print("Hello from my-cli!")
if name == "main":
main()
undefinedIncluding Data Files
包含数据文件
Include package data:
toml
[tool.setuptools.package-data]
my_package = ["data/*.json", "templates/*.html"]Include non-package files:
Create :
MANIFEST.ininclude README.md
include LICENSE
recursive-include src/my_package/data *包含包内数据文件:
toml
[tool.setuptools.package-data]
my_package = ["data/*.json", "templates/*.html"]包含非包内文件:
创建文件:
MANIFEST.ininclude README.md
include LICENSE
recursive-include src/my_package/data *Classifiers
分类器
Use PyPI classifiers to categorize your package:
toml
classifiers = [
# Development status
"Development Status :: 3 - Alpha",
"Development Status :: 4 - Beta",
"Development Status :: 5 - Production/Stable",
# Audience
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
# License
"License :: OSI Approved :: MIT License",
# Python versions
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
# Topics
"Topic :: Software Development :: Libraries",
"Topic :: Internet :: WWW/HTTP",
]Full list: https://pypi.org/classifiers/
使用PyPI分类器对包进行分类:
toml
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/
Building and Publishing
构建与发布
With UV (recommended):
bash
undefined使用UV(推荐):
bash
undefinedBuild distribution
构建分发包
uv build
uv build
Publish to PyPI
发布到PyPI
uv publish
uv publish
Or use twine
或使用twine
uv build
twine upload dist/*
**With setuptools:**
```bashuv build
twine upload dist/*
**使用setuptools:**
```bashInstall build tools
安装构建工具
pip install build twine
pip install build twine
Build distribution
构建分发包
python -m build
python -m build
Publish to PyPI
发布到PyPI
twine upload dist/*
undefinedtwine upload dist/*
undefinedTesting Installation
测试安装
Test your package locally before publishing:
bash
undefined在发布前本地测试包:
bash
undefinedInstall in editable mode with UV
使用UV以可编辑模式安装
uv pip install -e .
uv pip install -e .
Or with pip
或使用pip
pip install -e .
pip install -e .
Test the package
测试包
python -c "import my_package; print(my_package.version)"
python -c "import my_package; print(my_package.version)"
Test console scripts
测试控制台脚本
my-cli --help
undefinedmy-cli --help
undefinedCommon Patterns
常见模式
Multi-Package Project
多包项目
For projects with multiple packages:
toml
[tool.hatch.build.targets.wheel]
packages = ["src/package1", "src/package2"]对于包含多个包的项目:
toml
[tool.hatch.build.targets.wheel]
packages = ["src/package1", "src/package2"]Optional Dependencies
可选依赖
Group optional features:
toml
[project.optional-dependencies]
dev = ["pytest", "black", "mypy"]
docs = ["sphinx", "sphinx-rtd-theme"]
aws = ["boto3"]
all = ["pytest", "black", "mypy", "sphinx", "boto3"]Install with: or
pip install my-package[dev]pip install my-package[all]对可选功能进行分组:
toml
[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]Platform-Specific Dependencies
平台特定依赖
toml
[project]
dependencies = [
"requests",
"pywin32; platform_system=='Windows'",
"python-daemon; platform_system=='Linux'",
]toml
[project]
dependencies = [
"requests",
"pywin32; platform_system=='Windows'",
"python-daemon; platform_system=='Linux'",
]Validation
验证
Before publishing, verify:
-
Package builds successfully:bash
uv build # or python -m build -
Metadata is correct:bash
twine check dist/* -
Installation works:bash
uv pip install dist/*.whl -
Entry points work:bash
my-cli --version -
Imports work:python
import my_package print(my_package.__version__)
发布前,请验证以下内容:
-
包构建成功:bash
uv build # 或 python -m build -
元数据正确:bash
twine check dist/* -
安装正常:bash
uv pip install dist/*.whl -
入口点正常工作:bash
my-cli --version -
导入正常:python
import my_package print(my_package.__version__)
Troubleshooting
故障排除
Package not found after installation:
- Check package name vs. import name (hyphens vs. underscores)
- Verify package discovery configuration
- Ensure exists in package directory
__init__.py
Entry points not working:
- Verify function signature (should take no arguments or use argparse)
- Check entry point syntax:
"script-name = "package.module:function" - Reinstall package after changes
Data files not included:
- Add to in pyproject.toml
package-data - Or create MANIFEST.in
- Verify with:
python -m tarfile -l dist/*.tar.gz
Version conflicts:
- Use compatible version constraints (syntax)
>=,< - Test with different dependency versions
- UV automatically creates lock files for reproducibility
安装后找不到包:
- 检查包名称与导入名称的区别(连字符 vs 下划线)
- 验证包发现配置是否正确
- 确保包目录中存在文件
__init__.py
入口点无法工作:
- 验证函数签名(应无参数或使用argparse)
- 检查入口点语法:
"脚本名称 = 包.模块:函数" - 修改后重新安装包
数据文件未被包含:
- 在pyproject.toml中添加到
package-data - 或创建MANIFEST.in文件
- 使用以下命令验证:
python -m tarfile -l dist/*.tar.gz
版本冲突:
- 使用兼容的版本约束(语法)
>=,< - 测试不同的依赖版本
- UV会自动生成锁文件以确保可复现性