一、Poetry build产物与setuptools的核心差异

很多Python开发者在打包项目时,常会纠结Poetry和setuptools的选择,其中最核心的疑问就是两者的产物和逻辑有啥不一样,这部分就用大家能听懂的话拆解清楚。

1.1 打包生成的文件类型不同

setuptools打包时,通常需要你手动写setup.py或者setup.cfg,再用命令生成两种核心文件:源分发包(后缀.tar.gz)和车轮包(后缀.whl),这些文件会放到项目的dist文件夹里。但setuptools不会自动锁死依赖的精确版本,你得单独写requirements.txt来记录依赖,很容易出现不同环境下依赖版本不一致的问题。 而Poetry打包(用poetry build命令)不仅会生成同样的.tar.gz.whl文件,还会自动生成一个poetry.lock文件,这个文件会记录所有依赖的精确版本、哈希值,相当于给你的项目依赖上了“保险”,团队成员或其他用户拿到你的包后,安装的依赖完全和你打包时一致,不会踩版本坑。

1.2 依赖管理的逻辑不同

setuptools是“安装时才解析依赖”:当你用pip install安装setuptools打包的包时,pip会去PyPI上找满足install_requires字段里版本范围的最新版本,同一款包在不同时间安装,可能因为PyPI更新导致依赖版本不一样,出现莫名其妙的兼容性问题。 Poetry是“打包时就锁死依赖”:你在pyproject.toml里写依赖的版本范围(比如requests = "^2.25.0",表示兼容2.25.0及以上、但不到3.0.0的版本),Poetry会根据这个范围找稳定版本,然后把找到的精确版本写到poetry.lock里,不管谁安装,都会用这个精确版本,彻底解决依赖不一致的问题。

1.3 元数据的封装方式不同

元数据就是项目的“身份信息”,比如名字、版本、作者、描述这些,setuptools的元数据是分散在多个文件里的:名字和版本在setup.py,要包含的文件在MANIFEST.in,作者信息也在setup.py,很容易漏填某个字段导致打包失败。 而Poetry把所有元数据统一放到pyproject.toml[tool.poetry]块里,一目了然,还会自动处理MANIFEST.in的内容,不用你手动写规则,大大减少了漏填的概率。

二、pyproject.toml元数据字段完整填写指南

把元数据填全是发布到任何PyPI(包括内部和公共)的前提,漏填字段会导致发布被拒绝,或者别人不知道你的包有啥用,这里分必填字段、推荐字段和发布配置三部分讲,每个部分都带完整示例。

2.1 基础必填元数据(发布必须有,不然PyPI直接拒收)

基础字段是PyPI要求必须提供的核心信息,一个都不能少,以下是符合规范的示例,技术栈为Python:

[tool.poetry]
# 项目名:必须唯一,只能用小写字母、短横线和数字,不能和PyPI上已有项目重名
name = "my-demo-tool"
# 版本号:遵循语义化版本(MAJOR.MINOR.PATCH),每次发布必须升级,比如从1.0.0改到1.0.1
version = "1.0.0"
# 简短描述:控制在200字以内,清晰说明项目用途
description = "一个用于日常文本处理的轻量级Python工具包,支持批量清洗、格式转换"
# 作者信息:至少填一个,格式为“名字 <邮箱>”,方便用户联系
authors = ["李小明 <liming@example.com>"]
# 开源协议:选常用的标准协议,比如MIT、Apache-2.0,不能空着,不然别人不敢用
license = "MIT"
# 说明文档:指定你的README文件,必须是Markdown格式,放项目核心用法
readme = "README.md"

这里要注意几个细节:项目名不能用中文或大写,版本号不能重复,协议要选OSI认证过的,不然PyPI不识别。

2.2 可选但强烈推荐的扩展元数据(提升项目曝光和易用性)

这些字段能让你的包更受欢迎,比如让用户知道你支持哪些Python版本、项目仓库在哪,以下是推荐配置:

[tool.poetry]
# 项目主页:比如GitHub仓库地址,方便用户找源码
homepage = "https://github.com/liming/my-demo-tool"
# 代码仓库地址:和主页类似,是提交代码的地址
repository = "https://github.com/liming/my-demo-tool.git"
# 文档地址:比如Readthedocs的链接,放详细用法
documentation = "https://my-demo-tool.readthedocs.io"
# 关键词:最多5个,帮助用户搜索到你的包,比如用“text processing”“python tool”
# 分类标签:给项目打标签,让PyPI的用户能筛选到你的包,必须选标准分类
classifiers = [
    # 开发状态:5代表稳定版,3代表测试版,4代表开发中
    "Development Status :: 5 - Production/Stable",
    # 目标用户:开发者,适合技术类工具
    "Intended Audience :: Developers",
    # 协议:对应前面选的MIT
    "License :: OSI Approved :: MIT License",
    # 支持的Python版本:要和你的代码兼容的版本,这里示例支持3.8到3.11
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    # 操作系统:跨平台的话写OS Independent
    "Operating System :: OS Independent",
]

分类标签的选择很重要,比如如果你只支持Python 3.9以上,就把3.8去掉,避免给用户造成误解。

2.3 发布到内部或公共PyPI的额外配置

如果是发布到公共PyPI,直接用poetry publish命令就行,不用额外配置;如果是发布到公司内部的私有PyPI,需要在pyproject.toml里加仓库配置,再配置登录凭证:

[tool.poetry.repositories]
# 给内部PyPI起个名字,比如“internal-pypi”,方便后续引用
internal-pypi = "https://your-company-pypi.com/simple"

然后用命令配置你的账号和token(只需要运行一次):

# 替换成你的内部PyPI用户名和API token,token一般从内部PyPI的管理页面获取
poetry config http-basic.internal-pypi your-username your-api-token

发布到内部PyPI就用命令:poetry publish --repository internal-pypi,这样包就会推送到你的公司内部仓库,只有有权限的人才能安装。

三、应用场景、技术优缺点与注意事项

3.1 适用场景

Poetry适合现代Python项目,尤其是团队协作、需要严格依赖管理的项目,比如公司内部的工具包、开源项目;setuptools适合快速打包小型脚本、不需要复杂依赖管理的项目,比如个人写的小工具。

3.2 技术优缺点

Poetry的优点:依赖管理严格,不会出现版本不一致,元数据集中少出错,集成了打包、发布、虚拟环境管理的全流程;缺点是学习成本比setuptools高,需要熟悉poetry.lock的用法,老项目迁移需要调整配置。 setuptools的优点:简单易用,是Python的传统打包工具,大部分旧项目都用它;缺点是依赖管理弱,容易出现兼容性问题,元数据分散容易漏填,需要额外用requirements.txt管理依赖。

3.3 注意事项

  1. 发布前用poetry build -v检查生成的产物,确认所有需要的文件都被打包进去;
  2. 内部PyPI的token要妥善保存,不要提交到代码仓库,最好用环境变量或本地配置文件;
  3. 公共PyPI的项目名不能重复,发布前可以先在PyPI官网搜索确认;
  4. 每次发布必须升级版本号,不然会被PyPI拒绝,比如1.0.0发布过,下次只能用1.0.1或更高;
  5. 元数据里的README要写清楚安装方法、使用示例,不然用户拿到你的包不知道怎么用。

四、文章总结

Poetry和setuptools不是谁替代谁的关系,而是看项目的需求选择:现代项目尤其是团队协作的,优先选Poetry,它能解决setuptools容易出现的依赖和元数据问题;发布包的时候,元数据一定要填全,不管是公共还是内部PyPI,漏填都会导致问题,选对分类标签和关键词还能让你的包被更多人找到。只要按照本文的示例配置,就能顺利打包并发布Python包,避免踩常见的坑。