升级Airflow至2.4.2及以上版本后DAG无法加载的根因排查求助
Airflow 2.4.2+升级后DAG加载递归错误根因分析与修复方案
问题场景
- 环境:Docker镜像debian11-0.0.4、Python 3.9、40+个DAG
- 现象:Airflow v2.4.1运行正常,升级至v2.4.2或v2.5.0后DAG无法加载,抛出递归错误;将
airflow.cfg中日志级别从INFO改为ERROR后,DAG恢复正常加载与运行 - 报错信息:
File "/usr/local/lib/python3.9/site-packages/pendulum/tz/timezone.py", line 320, in _normalize dt = dt.__class__( RecursionError: maximum recursion depth exceeded while calling Python object - 无效尝试:调大
sys.setrecursionlimit()至100000,问题依旧
根因分析
pendulum版本升级引入递归bug
Airflow v2.4.2升级了依赖库pendulum的版本(从v2.1.1升级至v2.1.2+),该版本的pendulum/tz/timezone.py中_normalize方法存在逻辑缺陷:在创建新datetime对象时,传入当前时区self作为tzinfo,会再次触发该时区的_normalize方法,形成无限递归。日志级别触发递归累积
当日志级别为INFO时,Airflow加载DAG过程中会大量输出任务时区相关的日志,每一条日志都会触发pendulum的时区解析与_normalize调用;40+个DAG的批量加载会让递归调用快速累积,触发Python的递归深度限制。而ERROR级别下,Airflow会跳过这些时区相关的INFO级日志,避免了递归触发。调大递归限制无效的原因
该问题是无限递归而非单纯的递归深度不足,调大限制只会延迟错误触发,无法终止循环逻辑。
验证与修复方向
验证步骤
- 对比Airflow v2.4.1与v2.5.0的依赖清单,确认
pendulum版本差异 - 单独加载单个DAG并设置日志级别为
INFO,观察是否触发递归错误(验证是否是批量加载的累积效应) - 检查
pendulum仓库的issue记录,确认是否存在同类型时区递归bug报告
修复方案
方案1:修复pendulum的递归逻辑
定位pendulum/tz/timezone.py第320行的_normalize方法,修改datetime对象的创建逻辑,避免触发递归:
- 在实例化datetime时,添加递归终止条件,或绕过时区的二次校验
- 示例修改:
# 原代码 dt = dt.__class__( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond, tzinfo=self ) # 修改后 import datetime dt = datetime.datetime( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond, tzinfo=self )
方案2:修改Airflow的日志输出逻辑
- 在Airflow的DAG加载模块中,临时过滤掉
pendulum.tz相关的INFO级日志,避免触发递归调用 - 或在
airflow.cfg的日志配置中,添加对pendulum时区日志的过滤规则
内容的提问来源于stack exchange,提问作者PrashanjeetH
相关产品推荐
相关产品推荐

