资讯详情

Apache Airflow 依赖与 Extras 管理全解:从 uv Workspace 到约束文件(Constraints)的工程实践

📅 2026/9/11 10:38:19 | 华诺云谱 👁 阅读
Apache Airflow 依赖与 Extras 管理全解:从 uv Workspace 到约束文件(Constraints)的工程实践
Apache Airflow 依赖与 Extras 管理全解从 uv Workspace 到约束文件Constraints的工程实践【免费下载链接】airflowApache Airflow - A platform to programmatically author, schedule, and monitor workflows项目地址: https://gitcode.com/GitHub_Trending/ai/airflow本文以 Apache Airflow 仓库中的 contributing-docs/13_airflow_dependencies_and_extras.rst 为主线系统讲解 Airflow 如何在单仓库monorepo中管理超过 700 个依赖、100 多个 Python 发行包distribution以及如何通过约束文件机制让同一个项目既作为应用稳定安装、又作为库灵活复用。读完本文你将掌握 Airflow 的pyproject.toml依赖分区规则、uvworkspace 的工作方式、跨发行包引用的# use next version协作约定以及constraints-*.txt系列约束文件的使用方法并能在自己的 Airflow 开发中正确添加、修改和校验依赖。一、Airflow 的依赖管理全景为什么这是一个复杂工程Apache Airflow 不是一个普通的 Python 项目。在 pyproject.toml 中主发行包apache-airflow的元数据清楚地表明了这一特殊性[project] name apache-airflow requires-python 3.10,!3.15 version 3.4.0 dependencies [ apache-airflow-task-sdk1.5.0,1.4.0, apache-airflow-core3.4.0, ]从源码结构看Airflow 仓库是一个典型的 monorepo包含超过 100 个 Python 发行包主包apache-airflow、核心包apache-airflow-core、任务 SDKapache-airflow-task-sdk、控制面工具apache-airflow-ctl、大量apache-airflow-providers-*提供商包每个 provider 一个发行包以及若干apache-airflow-shared-*共享库见 shared 目录。这些发行包之间相互依赖、协同演进依赖管理因此成为开发流程中不可回避的核心环节——每当新增功能引入新依赖或新增一个用于开发、测试、文档构建的工具时都需要同步更新依赖列表。管理如此庞大的依赖体系Airflow 遵循了三个 PEP 标准PEP 518规定pyproject.toml作为项目构建配置的存放位置PEP 621规定[project]表用于声明元数据和依赖PEP 735引入依赖组dependency groupAirflow 在所有pyproject.toml中统一使用dev依赖组来定义开发依赖。二、uv Workspace把 monorepo 绑定在一起的粘合剂2.1 Workspace 的定义位置所有发行包通过uv的 workspace 特性连接起来workspace 定义在仓库根目录 pyproject.toml 的[tool.uv.workspace]表中[tool.uv.workspace] members [ ., airflow-core, airflow-e2e-tests, dev/breeze, dev/mypy, airflow-ctl, task-sdk, chart, kubernetes-tests, shared/configuration, shared/logging, shared/timezones, # Automatically generated provider workspace members (update_airflow_pyproject_toml.py) providers/airbyte, providers/amazon, providers/apache/beam, providers/google, # ... # End of automatically generated provider workspace members ]注意其中以# Automatically generated provider workspace members注释包裹的区块——这些是自动生成的由prek工具负责维护开发者不应手工修改。同文件中的[tool.uv]还定义了 workspace 层面的约束例如[tool.uv] required-version 0.11.8 exclude-newer 4 daysrequired-version是贡献者必须安装的最低uv版本而非 CI 固定的版本exclude-newer则限制解析时忽略过于新的包版本保证依赖解析的可复现性。2.2 Workspace 带来的开发体验Workspace 特性使开发者可以在仓库根目录直接运行uv sync一次性完成三件事以 editable 模式安装所有发行包将所有发行包的依赖放在一起统一解析从而提前发现不同包之间是否存在版本冲突发行包之间按名称互相引用因此本地解析时优先使用仓库中的本地版本而不是 PyPI 上已发布版本。这意味着你可以同时开发跨多个发行包的改动——例如给被多个 provider 共用的公共发行包新增一个功能并在本地把所有依赖它的 provider 一起测试再统一发布。这正是 Airflow 能以单个 monorepo 维持整个生态的前提。2.3 仓库中的佐证[tool.uv]的依赖覆盖表在 pyproject.toml 的[tool.uv.exclude-newer-package]区块中所有 workspace 成员包括自动生成的 provider 列表都被标记为false即不对这些本地发行包应用exclude-newer限制——因为它们在本地解析时使用源码版本与新近发布无关。这从实现层面印证了 workspace 成员优先使用本地源码的机制。三、pyproject.toml 中的三个依赖区段每个发行包的 pyproject.toml例如 airflow-core/pyproject.toml、task-sdk/pyproject.toml、airflow-ctl/pyproject.toml、各 providers 下的 provider 包都在以下三个区段中声明依赖区段作用何时被安装[project.dependencies]包的必需依赖不带 extras 安装该包时即安装[project.optional-dependencies]可选依赖extras带 extras 安装时安装如pip install apache-airflow[ssh][dependency-group.dev]开发依赖uv sync默认安装同时包以 editable 模式安装以 providers/google/pyproject.toml 为例其[project]下同时出现了普通依赖与带环境标记的依赖dependencies [ apache-airflow2.11.0, apache-airflow-providers-common-compat1.13.0, apache-airflow-providers-common-sql1.32.0, asgiref3.5.2; python_version 3.14, asgiref3.11.1; python_version 3.14, google-cloud-bigquery-storage2.31.0;python_version3.13, google-cloud-bigquery-storage2.33.0;python_version3.13, ]同一依赖可以针对不同 Python 版本给出不同下界这也是 Airflow 支持 Python 3.103.14 多种解释器的具体体现见根 pyproject.toml 的 classifiers。四、如何正确添加和修改依赖在 Airflow 中添加/修改依赖的方式是编辑对应发行包的pyproject.toml。提交前需要遵循一套明确的规则。4.1 放到正确的区段新增依赖时首先判断它是主依赖[project.dependencies]、可选依赖[project.optional-dependencies]还是开发依赖[dependency-group.dev]。4.2 警惕自动生成的依赖区块部分依赖由prekhooks自动生成并覆盖。prek通过分析源码中的 import 和项目结构能自动推导出必要的依赖。以根 pyproject.toml 的[project.optional-dependencies]为例可以看到明显的自动生成区块[project.optional-dependencies] # Automatically generated airflow optional dependencies (update_airflow_pyproject_toml.py) all-core [ apache-airflow-core[all] ] async [ apache-airflow-core[async] ] # ... common.compat [ apache-airflow-providers-common-compat1.2.1 ] # ... # End of automatically generated airflow optional dependencies凡是位于# Automatically generated ...与# End of automatically generated ...注释之间的内容都不应手工修改——它们会在prekhook 运行时被整体重写。如果你需要调整应当修改这些依赖的根来源如update_airflow_pyproject_toml.py脚本中的生成逻辑而手工新增的依赖则应放在注释区块之外。4.3 版本说明符的两条铁律上界要尽量开放Airflow 极少对依赖设置上界upper-bound只有当已知某个新版本会破坏安装或测试时才上界且必须注释说明原因。仓库中 providers/google/pyproject.toml 就有一个典型例子google-ads26.0.0,!28.0.0.post2,以及带详细说明的抬高下界注释# Floor raised to 2.30.3: google-api-core 2.28.1-2.30.2 has an import-time # performance regression (it scans the whole venv on import), which trips the # Dag import timeout for operators that import it. Fixed in 2.30.3. google-api-core2.30.3,下界必须存在任何从 PyPI 解析的依赖都必须有下界。没有下界时解析器可能选择历史上任意一个旧版本导致最终安装的版本取决于解析过程而非代码实际需求。prek的check-dependency-lower-boundshook 会在project.dependencies、project.optional-dependencies、dependency-groups以及build-system.requires中全面强制这一规则。下界的取值原则是使用你愿意测试的最老版本例如pyspark4.0.0,两条豁免情形属于uvworkspace 成员的发行包它们从本地源码解析版本区间无意义以及直接指定 URL 的依赖URL 本身已精确指代构件。4.4 修改后必须验证修改依赖后务必运行uv sync验证 workspace 内各包依赖之间没有冲突在仓库根目录运行同步所有包在修改的包目录运行只同步该包及其依赖更彻底的验证在根目录运行uv sync --all-packages --all-extras确认所有包连同所有 extras 能一起无冲突安装。最后再运行全部测试确保改动没有破坏任何功能。需要注意--all-extras模式可能较慢且困难因为部分 extras如mysql、postgres要求系统预先安装客户端库。4.5 CI 的兜底校验即使本地没有发现问题CI 也会对依赖做下界检查——例如逐个 provider 尝试用尽可能低的依赖版本解析并运行测试防止把下界定得过低。因此本地先跑uv sync能尽早发现问题避免浪费 CI 资源。五、跨发行包引用常规依赖与共享依赖机制仓库内存在大量发行包开发时经常需要在一个包中引用另一个包的功能。Airflow 提供两种方式5.1 常规包依赖Workspace 名称引用直接用发行包名称声明依赖即可。例如在apache-airflow-providers-google中引用apache-airflow-providers-common-compatapache-airflow-providers-common-compat1.13.0,得益于 workspace 特性uv sync时会自动使用本地版本。这类依赖如果位于源码顶层 import 中prekhook 通常能自动识别并写入自动生成区块如果依赖没有出现在顶层 import例如条件导入则需要手工添加。5.2 共享依赖Shared Dependencies机制对于需要在多个发行包之间静态链接的公共代码Airflow 采用了自研的 shared dependencies 机制避免不必要的耦合和循环依赖。详细设计见 shared/README.md其核心要点包括共享方式使用仓库内符号链接symlink同一份代码只保存一份无需prek更新多份拷贝动机如果两个发行包同时依赖 PyPI 上的某个共享发行包就会引入版本地狱改为类似 vendoring/静态链接的方式每个发行包自带它验证过的版本可以在同一 Python 环境中共存导入约束共享库内部引用其他共享库必须使用相对导入与 Airflow 主代码库禁止相对导入的约定相反例如from ..timezones.timezone import is_naive目录结构共享库按airflow_shared/name组织如shared/timezones、shared/logging打包集成使用共享库的发行包需要在pyproject.toml的[tool.airflow]中声明shared_distributions并在[tool.hatch.build.targets.sdist.force-include]中把共享源码复制进 sdist符号链接在构建 sdist 时无效构建 wheel 时会解析符号链接。六、# use next version跨包新特性的协作约定当你给某个公共发行包如apache-airflow-providers-common-compat添加新特性并希望同一 PR 中的另一个发行包立即使用它时就会面临一个时间差问题新特性只会在公共包未来的发布中才可用你不能在依赖里写上尚未发布的版本号。Airflow 的解决方案是贡献者永远不手工修改跨包依赖的版本版本号只由 Release Manager 在同时准备两个包的发布时统一提升。贡献者的责任是在依赖行末尾加上一个精确的注释apache-airflow-providers-google1.2.0, apache-airflow-providers-common-compat5.5.0, # use next version requests2.25.1,⚠️警告必须使用精确的注释文本# use next version否则自动化工具无法识别。配套的自动化机制包括检查普通 PR 不会修改这类跨依赖版本在准备发布时自动将带此注释的依赖更新为即将发布的下一个版本例如上例中的5.6.0并确保两个包同步发布当prekhook 自动生成了跨包依赖行时位于自动生成注释区块内你应当把这行复制到注释区块外并加上# use next version下次运行prek时自动生成的行会被删除只保留手工添加的那行。6.1 common.compat 的特殊检查common.compatprovider 是变更最频繁、最常触发连锁更新的公共包因此对它有专门的自动化检查一旦修改了common.compat且其他 provider 需要随之更新Selective Check CI 任务会报错提醒你为相关 provider 添加# use next version注释。如果确认没有其他 provider 需要更新可以给 PR 打上skip common compat check标签跳过检查该标签只有 maintainer 和 collaborator 能添加。6.2 强制最低版本MIN_VERSION_OVERRIDE部分依赖存在强制最低版本主要出于 Airflow 3 最低版本兼容性考虑例如git、common.messaging等 provider或已知旧版本功能已失效如amazon、fab。这些版本由 scripts/ci/prek/update_airflow_pyproject_toml.py 中的MIN_VERSION_OVERRIDE字典控制第 91 行起定义生成的依赖行带固定注释apache-airflow-providers-fab2.2.0, # Set from MIN_VERSION_OVERRIDE in update_airflow_pyproject_toml.py如果某发行包依赖了比强制值更新的版本该注释不会出现。你可以自由把这类版本改成更高值prek会自动移除注释。七、Airflow 的双重身份与约束文件方案7.1 为什么需要约束文件Airflow 不是标准的 Python 项目。绝大多数 Python 项目可以归入两类应用application依赖应该被固定pin保证未来安装的稳定性——因为新的甚至传递的依赖可能导致安装失败库library依赖应该保持开放允许多个有相同需求的库共存。而 Airflow 同时是两者它是用户要安装的应用也是开发者编写自定义 operator 和 DAG 时依赖的库。这个看似无解的矛盾最终靠固定的约束文件pinned constraints files解决。7.2 为什么不用标准方案因为 Python 生态的现有标准尚未跟上既是库又是应用的复杂项目的可复现安装需求。Airflow 的做法更像一个弥补现有工具局限的hack。近年来标准讨论有所进展PEP 751提出了pylock.toml格式用于记录安装可复现的依赖但截至 2025 年 11 月该格式在pip中仍是实验性的uv也只是将其作为自有锁文件面向开发环境的导出格式尚不足以支撑 PEP 751 设想的可复现安装场景PEP 751 本身也尚未完整到能支持该用途。社区仍在推进后续 PEP 以支持 Airflow 多年前用约束文件 hack 实现的这种可复现安装流程。7.3 官方支持的安装工具只有 pip 和 uv 的安装方式得到官方支持。虽然用poetry、pip-tools安装也有成功案例但它们与pip的工作流不共享——尤其在约束constraint与需求requirement的管理上差异明显目前不支持通过 Poetry 或 pip-tools 安装。uv通过uv pip遵循pip的方式因此可以正常工作。已知bazel存在可能导致循环依赖的问题遇到时请改用piprules_python社区已在跟进解决较新版本的 bazel 或许能处理。若坚持使用上述工具应把约束文件转换为目标工具要求的格式和工作流后再使用。7.4 三套约束文件默认情况下pip install apache-airflow安装的依赖尽可能开放因此当某个直接或传递依赖发布破坏性新版本时安装可能失败。此时需要提供额外约束例如pip install apache-airflow1.10.2 Werkzeug1.0.0Airflow 维护三套约束文件均以 Python 主次版本号命名如constraints-3.10.txt约束集生成方式用途constraints匹配当前源码中的 Airflow 版本 从 PyPI 安装的 providers普通用户用 pip 安装 Airflowconstraints-source-providers使用当前源码安装的 providers 生成CI 系统维持稳定约束从源码以 editable 模式安装时使用constraints-no-providers仅 Apache Airflow 本体不含任何 provider想单独管理 Airflow、再逐个添加 provider 的场景从 PyPI 包安装可重复安装pip install apache-airflow[google,amazon,async]3.0.0 \ --constraint https://raw.githubusercontent.com/apache/airflow/constraints-3.0.0/constraints-3.10.txt从源码以 editable 模式安装应使用constraints-source-providers它考虑了部分 provider 尚未发布、需求可能冲突的情况pip install -e .[devel] \ --constraint https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-source-providers-3.10.txt带 extras 从源码安装pip install .[ssh] \ --constraint https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-source-providers-3.10.txt只更新 Airflow 本体依赖、忽略 providerspip install . --upgrade \ --constraint https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-no-providers-3.10.txt注意不同 Python 主/次版本对应不同的约束文件务必为当前解释器选择正确的文件。7.5 约束文件的生成机制约束文件由仓库中提交的uv.lock文件生成通过uv export --frozen把锁文件导出为适合pip install --constraint的扁平固定版本列表。这意味着约束文件始终与开发者uv sync安装的依赖版本保持一致。在仓库的 constraints 目录中可以查看相关说明constraints/README.md。此外constraints-PYTHON_MAJOR_MINOR_VERSION.txt与constraints-no-providers-PYTHON_MAJOR_MINOR_VERSION.txt会在pyproject.toml更新并推送后由 CI 任务在测试通过时自动重新生成——开发者无需手工维护这两个文件。八、apache-airflow 包的可选依赖Extras安装 Airflow 时可以指定大量 extras例如pip install -e .[ssh]editable 安装或pip install apache-airflow[ssh]普通安装。extras 分两类常规 extras面向最终用户如ssh、google、amazon、async开发类 extraseditable 模式下用于本地测试的devel以及用于构建文档的doc安装文档构建工具。需要特别说明的是部分 extras 只定义在元发行包apache-airflow中并不在airflow-core或其他包中定义。从根 pyproject.toml 的[project.optional-dependencies]可以看到这种代理式定义——很多 extras 只是转发到 core 包或 provider 包async [ apache-airflow-core[async] ] amazon [ apache-airflow-providers-amazon9.0.0 ] common.compat [ apache-airflow-providers-common-compat1.2.1 ]把 provider 依赖和这类 extras 从apache-airflow包自动复制到各发行包同样由prekhooks 完成。此外还有一些为常用可选功能手工定义的 extras。完整的 extras 清单可查阅仓库内的 airflow-core/docs/extra-packages-ref.rstextras reference。九、小结与延伸阅读Airflow 的依赖管理可以概括为三句话开发期用uvworkspace 把所有发行包绑定在 monorepo 中统一解析、editable 安装prekhooks 自动维护可推导的依赖区块协作期跨包依赖的版本号一律交给 Release Manager贡献者只用# use next version注释表达发布时请提升版本的意图发布与安装期用从uv.lock导出的三套constraints-*.txt约束文件让 Airflow 同时满足应用级可复现安装与库级开放依赖的双重需求。对开发者而言动手修改依赖时的核心检查清单是选对区段、避开自动生成区块、保证下界存在且合理、上界只在必要时添加并注释理由、修改后运行uv sync必要时加--all-packages --all-extras并跑全量测试。如果你接下来需要更新 Airflow 的元数据库结构可以继续阅读 contributing-docs/14_metadata_database_updates.rst 了解迁移流程。【免费下载链接】airflowApache Airflow - A platform to programmatically author, schedule, and monitor workflows项目地址: https://gitcode.com/GitHub_Trending/ai/airflow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。