当前位置:首页 > 文章列表 > 文章 > python教程 > Python 打包发布实战:别把运行依赖和开发依赖混在一起

Python 打包发布实战:别把运行依赖和开发依赖混在一起

来源:Python 博主原创 2026-06-04 14:58:47 0浏览 收藏

Python 项目一开始常常只有一个 requirements.txt。等服务变成内部 SDK、命令行工具、后台任务包以后,问题就来了:运行环境装进 pytest 和 black,构建机和线上版本不一致,私有源 token 散落在脚本里,发布出来的 wheel 在另一台机器上装不上。

这篇文章不讲“怎么上传 PyPI”的入门流程,而是按生产发布事故来写:如何用 pyproject.toml 收口元数据和构建后端,如何拆运行依赖、开发依赖和构建依赖,为什么构建隔离能帮你发现隐性依赖,以及上线前怎么检查 wheel、sdist、锁文件和私有仓库凭据。

Python 打包发布治理思维导图
治理思路:元数据、依赖分组、构建隔离、锁定文件、发布凭据和回滚路径要一起看。

业务场景:内部 SDK 发布后线上装不上

假设团队维护一个订单 SDK,FastAPI 服务、Celery worker、自动化脚本都会依赖它。最初项目里只有一个 requirements.txt,里面混着运行依赖、测试工具、格式化工具和构建工具。

requests
pydantic
pytest
black
setuptools
twine
uvicorn

本地开发没问题,CI 也能跑。但发布到私有仓库后,线上安装时发现依赖过重,有些机器还因为构建依赖缺失失败。根因很简单:我们没有区分“包运行需要什么”“开发测试需要什么”“构建这个包需要什么”。

第一步:把项目元数据放进 pyproject.toml

现代 Python 包应该让 pyproject.toml 成为入口。它不是某个工具的私货,而是 Python 打包生态的统一配置载体。最小可用结构通常包含 [project][build-system]

[project]
name = "order-sdk"
version = "0.8.3"
requires-python = ">=3.11"
dependencies = [
  "requests>=2.32",
  "pydantic>=2.7",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

dependencies 只放运行时真正需要的包。pytest、ruff、mypy、twine、build 这类工具不该被线上服务跟着安装。依赖越清楚,供应链扫描、镜像体积、冷启动和故障排查都会简单不少。

Python 从 pyproject 到可发布包流水线
发布流水线:解析 pyproject、安装测试依赖、构建隔离环境、生成 wheel/sdist、检查后上传。

第二步:开发依赖用 dependency-groups 分出来

如果你的工具链支持 dependency-groups,可以把测试、格式化、文档依赖拆开。这样 CI 可以按需安装,线上包只声明运行依赖。

[dependency-groups]
test = [
  "pytest>=8.2",
  "pytest-cov>=5",
]
lint = [
  "ruff>=0.5",
  "mypy>=1.10",
]
release = [
  "build>=1.2",
  "twine>=5",
]

我的习惯是:运行依赖写进 [project].dependencies,测试依赖进 test,代码质量工具进 lint,发布工具进 release。不要因为“CI 方便”就把所有东西塞回一个文件。

第三步:用构建隔离暴露隐性依赖

最怕的构建问题,是本地能构建,干净环境不能构建。原因通常是你机器上已经装过某个包,构建脚本偷偷依赖它,但 [build-system].requires 没声明。

python -m pip install --upgrade build
python -m build

python -m build 会在隔离环境中构建 sdist 和 wheel。它能逼你把构建依赖写清楚,也能避免宿主环境污染构建结果。CI 里我会从空环境开始构建,而不是复用开发虚拟环境。

Python 依赖分组和打包风险写法对照
代码审查重点:运行依赖、测试依赖、构建依赖混放,会让发布和线上安装都不可预测。

第四步:发布前检查 wheel 和 sdist

很多包不是上传失败,而是上传成功以后才发现缺文件、版本号错、元数据错。发布前至少做三件事:

python -m build
python -m twine check dist/*
python -m pip install --force-reinstall dist/order_sdk-0.8.3-py3-none-any.whl

如果包里有模板、配置样例、迁移文件、类型声明文件,别只看源码目录,要实际安装 wheel 后跑一次最小用例。wheel 能安装,不代表文件齐;文件齐,也不代表导入路径正确。

锁文件不是发布包元数据的替代品

锁文件的价值是让应用部署可复现,而不是让库包把所有下游版本钉死。内部应用可以锁定完整依赖树;内部 SDK 通常只声明合理版本范围,让使用方在自己的应用锁文件里统一解析。

如果团队已经开始使用 pylock.toml 或工具生成的 lock 文件,我建议把它纳入应用仓库 CI:构建镜像、跑测试、生成 SBOM、部署回滚都基于同一份锁定结果。库包则重点保证 dependencies 语义正确,不随手写死过窄版本。

私有源发布:token 不进代码库

发布到私有仓库时,凭据管理比命令本身重要。CI 里使用最小权限 token,只允许上传目标项目;token 存在 CI secret,不写进 pyproject.toml、脚本和镜像层。

python -m twine upload   --repository-url "$PRIVATE_PYPI_URL"   -u "__token__"   -p "$PRIVATE_PYPI_TOKEN"   dist/*

发布脚本要打印版本、仓库地址、构建产物摘要,但不要打印 token。出了问题时,日志应该帮你定位版本和产物,不应该帮别人拿到发布权限。

上线检查清单

  • [project].dependencies 只包含运行时依赖,不混入测试、格式化、发布工具。
  • [build-system].requires 完整声明构建后端和构建依赖。
  • 开发依赖按 testlintrelease 分组,CI 按需安装。
  • 构建必须在干净隔离环境执行,不能依赖本机已安装包。
  • 发布前执行 twine check,并从 wheel 安装跑最小导入用例。
  • 应用部署使用锁文件保证可复现,库包依赖范围不要无脑钉死。
  • 私有源 token 使用 CI secret 和最小权限,不进代码库、不进镜像层。

总结

Python 打包发布的核心不是命令,而是边界。运行依赖、开发依赖、构建依赖、部署锁定、发布凭据,各自解决不同问题。把它们混在一个文件里,短期省事,长期会把 CI、线上安装和供应链治理都变得很脆。

我的经验是,先把 pyproject.toml 写干净,再让 CI 用干净环境构建,最后用 wheel 安装结果验证发布物。这样一个 Python 包从本地开发到私有源,再到线上服务安装,才算真正可控。

版本声明
本文转载于:Python 博主原创 如有侵犯,请联系study_golang@163.com删除
MySQL 8.4 Buffer Pool 预热实战:重启后 P99 为什么突然飙高MySQL 8.4 Buffer Pool 预热实战:重启后 P99 为什么突然飙高
上一篇
MySQL 8.4 Buffer Pool 预热实战:重启后 P99 为什么突然飙高
Go errgroup 实战:并发扇出别把错误和取消弄丢
下一篇
Go errgroup 实战:并发扇出别把错误和取消弄丢
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ChatExcel酷表:告别Excel难题,北大团队AI助手助您轻松处理数据
    ChatExcel酷表
    ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
    5969次使用
  • Any绘本:开源免费AI绘本创作工具深度解析
    Any绘本
    探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
    6388次使用
  • 可赞AI:AI驱动办公可视化智能工具,一键高效生成文档图表脑图
    可赞AI
    可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
    6198次使用
  • 星月写作:AI网文创作神器,助力爆款小说速成
    星月写作
    星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
    8172次使用
  • MagicLight.ai:叙事驱动AI动画视频创作平台 | 高效生成专业级故事动画
    MagicLight
    MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
    6781次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码