# pyproject.toml 声明构建系统(PEP 518)
[build-system]
requires = ["setuptools>=61.0.0", "wheel"]
build-backend = "setuptools.build_meta"
# setup.cfg 声明包元数据
[metadata]
name = my_package
version = 1.0.0
# setup.py 复杂配置入口(可选)
import setuptools
setuptools.setup()
my_package/
├── src/
│ └── my_package/ # 包源代码
│ ├── __init__.py
│ └── module.py
├── tests/ # 测试代码
├── docs/ # 文档
├── setup.cfg # 主要配置
├── setup.py # 复杂逻辑入口
├── pyproject.toml # 构建系统配置
├── MANIFEST.in # 额外文件包含规则
└── README.md
setup.cfg
核心配置[metadata]
name = my-awesome-package
version = attr: my_package.__version__
description = 革命性的Python工具
long_description = file: README.md
long_description_content_type = text/markdown
author = 张伟
author_email = [email protected]
license = MIT
url = https://github.com/zhangwei/my_package
classifiers =
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Programming Language :: Python :: 3
[options]
package_dir =
= src
packages = find:
install_requires =
requests>=2.25
numpy
python_requires = >=3.8
include_package_data = True
[options.packages.find]
where = src
setup.py
高级配置#!/usr/bin/env python
import setuptools
import re
# 动态读取版本号
def get_version():
with open("src/my_package/__init__.py") as f:
return re.search(r'__version__\s*=\s*[\'"]([^\'"]*)[\'"]', f.read()).group(1)
# C扩展编译
my_extension = setuptools.Extension(
'my_package.accelerate',
sources=['src/my_package/accelerate.c'],
include_dirs=['/usr/local/include'],
)
# 自定义安装后操作
class CustomInstall(setuptools.command.install.install):
def run(self):
super().run()
print("执行自定义安装后操作...")
setuptools.setup(
version=get_version(),
ext_modules=[my_extension],
cmdclass={'install': CustomInstall}
)
[options]
install_requires =
base_lib>=1.2
[options.extras_require]
test =
pytest>=6.0
coverage
dev =
%(test)s
black
flake8
gui =
pyqt5
[options.extras_require]
# 特定平台依赖
:sys_platform == "win32" =
pywin32
:sys_platform == "linux" =
dbus-python
# Python版本限定
:python_version < "3.8" =
typing_extensions
MANIFEST.in
模式# 包含所有.md文件
include *.md
# 递归包含data目录
recursive-include src/my_package/data *
# 排除测试数据
exclude tests/test_data/*
[options.entry_points]
console_scripts =
my-tool = my_package.cli:main
gui_scripts =
my-gui = my_package.gui:launch
# 框架集成点
flask.commands =
seed = my_package.management:seed_db
[options.package_data]
my_package =
data/*.json
locales/*.mo
templates/*.html
# 非包数据文件
[options.data_files]
share/my_package =
config/default.yaml
/etc/my_package =
config/production.yaml
from setuptools import setup, Extension
import sys
define_macros = []
if sys.platform == "win32":
libraries = ['ole32']
else:
libraries = []
extensions = [
Extension(
'my_package.accelerate',
['src/accelerate.c'],
define_macros=define_macros,
libraries=libraries,
extra_compile_args=["-O3"]
)
]
setup(ext_modules=extensions)
from setuptools import setup
import platform
# 平台特定数据文件
data_files = []
if platform.system() == "Windows":
data_files.append(('Lib/site-packages/my_package', ['data/win_dlls/*']))
elif platform.system() == "Darwin":
data_files.append(('/usr/local/lib', ['data/mac_libs/*']))
setup(data_files=data_files)
# 安装构建工具
python -m pip install --upgrade build
# 创建wheel包
python -m build --wheel
# 检查包质量
python -m pip install twine
twine check dist/*
# 上传到PyPI
twine upload dist/*
#!/bin/bash
# release.sh
set -e
# 清理环境
rm -rf build dist
# 更新版本
bumpversion patch # 使用bumpversion管理版本
# 构建包
python -m build
# 测试安装
python -m venv test-env
source test-env/bin/activate
pip install dist/*.whl
pytest
deactivate
# 发布
twine upload dist/*
pure_python_pkg/
├── src/
│ └── package/
│ ├── __init__.py
│ └── core.py
├── tests/
├── setup.cfg
├── pyproject.toml
└── MANIFEST.in
with_c_extension/
├── src/
│ ├── package/
│ │ ├── __init__.py
│ │ └── core.py
│ └── c_src/ # C源代码目录
│ ├── module.c
│ └── header.h
├── setup.py # 处理C扩展编译
├── CMakeLists.txt # 可选CMake支持
└── .github/workflows/ # 多平台CI
├── linux.yml
├── windows.yml
└── macos.yml
cli_tool/
├── src/
│ └── package/
│ ├── __init__.py
│ ├── cli/ # CLI模块
│ │ ├── __main__.py
│ │ └── commands.py
├── setup.cfg
[options.entry_points]
console_scripts =
my-tool = package.cli.__main__:main
# 生成GPG密钥
gpg --gen-key
# 签名包
gpg --detach-sign -a dist/package-1.0.0.tar.gz
# 验证签名
twine upload --sign --identity [email protected] dist/*
# 安装生成工具
pip install cyclonedx-bom
# 生成软件物料清单
cyclonedx-py -o bom.xml
[metadata]
license_files =
LICENSE
NOTICE
# 供应商信息
project_urls =
Source = https://github.com/your/project
Security = https://github.com/your/project/security
# 错误方式:硬编码路径
data_files = [('/usr/share/data', ['data/file.csv'])]
# 正确方案:使用平台逻辑
from sys import platform
from setuptools import setup
if platform == "win32":
target = "$env:ProgramData/MyApp"
elif platform == "darwin":
target = "/Library/Application Support/MyApp"
else:
target = "/usr/share/myapp"
setup(data_files=[(target, ['data/file.csv'])])
# setup.py
import re
import os
def get_version():
# 优先使用环境变量(CI环境)
if "RELEASE_VERSION" in os.environ:
return os.environ["RELEASE_VERSION"]
# 从Git标签获取
try:
from setuptools_scm import get_version
return get_version()
except ImportError:
pass
# 从代码读取
version_file = "src/package/__init__.py"
with open(version_file) as f:
return re.search(r'__version__ = "(.+?)"', f.read()).group(1)
setup(version=get_version())
# setup.cfg
[options]
include_package_data = True
# MANIFEST.in
include src/package/templates/*.html
recursive-include src/package/static *
任务 | 推荐工具 |
---|---|
版本管理 | bumpversion / setuptools-scm |
依赖解析 | pip-tools |
包构建 | build |
包发布 | twine |
多平台构建 | cibuildwheel |
文档生成 | Sphinx + readthedocs |
合规扫描 | cyclonedx-bom |
通过本教程,您将掌握:
专家建议:使用
check-manifest
工具验证文件包含完整性,定期运行pip-audit
检查依赖漏洞。
遵循这些专业打包范式,让您的Python项目具备工业级分发质量,轻松应对从个人工具到企业级组件的各种分发场景!