起因: 由于公司里面使用airflow进行调度,昨晚一个依赖任务失败了,导致需要重跑我的任务。今天早上同事的依赖任务跑完后,我这边就需要接着重跑自己的任务。这时我发现了,原来我之前的代码是通过datetime来获取日期,然后对hive表进行处理。由于刚好过了一天,这时候如果我重跑的话,处理的是下一天的数据。如果需要重跑还需要修改代码,这让我觉得我的代码还需要优化。
一开始,我就想通过Variable来进行配置,这样的话,如果下次重跑,我这边修改一下Variable,重跑完了,再删除变量就可以了。跟一个经常重跑任务的同事沟通了一下,他建议自己写一个脚本来单独重跑,这让我觉得不太合理,直接告诉我应该有更方便的方式。
这是我之前获取前一天日期代码,非常粗暴简单。。。
yesterday_str = (datetime.now() - timedelta(1)).strftime("%Y-%m-%d")
找了一些资料后,我发现不止有Variable,airflow还内置了好多macros, Macros reference. 其中就有我所需要的{{ yesterday_ds }}
和 {{ ds }}
.
确认完了之后,我就把这两个macro放入PythonOperator里面的op_kwargs参数内。在我本地调试是没有问题的。
xxx_task = PythonOperator(
task_id='xxx',
provide_context=True,
python_callable=xxx,
op_kwargs={"ds_str": '{{ yesterday_ds }}'},
dag=dag,
)
结果merge到项目后,{{ yesterday_ds }}
并未如期转成Execution Date的前一天,而是原来的文本 {{ yesterday_ds }}, 后来上去服务器查了一下airflow版本,发现是1.9.0. 再看了一下源码, 对比之后发现新版本把op_args和op_kwargs都支持渲染了。所以我们的代码又要以templates_dict传入参数。
template_fields = ('templates_dict')
对比1.10版本的同一行
template_fields = ('templates_dict', 'op_args', 'op_kwargs')
不过还好在调试的过程中,我也把provide_context的内容打印出来,发现其实ds和yesterday_ds已经在context里面了,也就是说我们不需要传任何参数进去,只要在context提供的内容取出对应的值即可。
def xxx(**kwargs):
today = kwargs["ds"]
yesterday = kwargs["yesterday_ds"]
pass
xxx_task = PythonOperator(
task_id='xxx',
provide_context=True,
python_callable=xxx,
dag=dag,
)
当然macros还有更复杂的使用,有了这个设置之后,以后重跑哪一天的dag就只会使用那一天的相关数据,而不需要修改代码了。