task_id
task_id 是每个任务的唯一标识符,用于标记 DAG 中的任务。它是 Airflow 中任务的核心属性之一,类似task的身份证,必须在同一个 DAG 中保持唯一。在Airflow的Web UI界面中,task_id用于显示任务的状态、日志和执行历史,日志文件的命名也会包含task_id,可以通过task_id来快速找到任务的日志和状态。此外在任务之间通过XCom传递数据时也需要用task_id来标识数据的来源任务。
使用示例
task_a = PythonOperator(
task_id="task_a", # 唯一标识符
python_callable=task_function
)
task_b = PythonOperator(
task_id="task_b", # 唯一标识符
python_callable=task_function
)
task_a >> task_b # 定义依赖关系
在需要循环生成task时,可以通过生成不同的task_id来区分任务,下面这个示例中生成了三个task:
for i in range(3):
task = PythonOperator(
task_id=f"dynamic_task_{i}", # 动态生成唯一的 task_id
python_callable=task_function
)
由于定义task依赖关系时使用的是变量名,而上面循环生成的三个task对应的变量名是一致的,所以需要使用键值对的方式来进行生成task和定义依赖,具体如下所示:
tasks = {}
for i in range(3):
tasks[f'task_{i}'] = PythonOperator(
task_id=f'task_{i}',
python_callable=my_function
)
# 定义依赖关系
tasks['task_0'] >> tasks['task_1'] >> tasks['task_2']
当需要从XCom中获取指定任务的数据时:
def push_data_to_xcom(**kwargs):
ti = kwargs['ti']
ti.xcom_push(key='example_key', value='Hello, XCom!') # 推送数据到 XCom
def pull_data_from_xcom(**kwargs):
ti = kwargs['ti']
value = ti.xcom_pull(task_ids='push_task', key='example_key') # 从 push_task 中提取数据
print(f"Pulled value: {value}")
with DAG(
...
) as dag:
push_task = PythonOperator(
task_id='push_task',
python_callable=push_data_to_xcom,
provide_context=True,
)
pull_task = PythonOperator(
task_id='pull_task',
python_callable=pull_data_from_xcom,
provide_context=True,
)
# ti即task instance,是airflow中的任务实例对象
# xcom用于存储任务生成的数据,可以通过pull和push在不同的task中传递数据
provide_context
provide_text用于向PythonOperator的task中提供执行上下文,允许任务函数访问调度任务时的上下文变量,比如dag、ti(task_instance)、execution_date等。
使用示例
def print_context(**kwargs):
execution_date = kwargs.get('execution_date')
task_instance = kwargs.get('task_instance')
print(f"Execution Date: {execution_date}")
print(f"Task Instance: {task_instance}")
dag = DAG(
'example_provide_context',
schedule_interval='@daily',
start_date=datetime(2023, 1, 1),
catchup=False
)
# 使用 PythonOperator 并启用 provide_context
task = PythonOperator(
task_id='print_execution_context',
python_callable=print_context,
provide_context=True, # 使print_context函数可以通过kwargs来接收Airflow提供的上下文信息
dag=dag
)
打印结果为任务执行日期和实例等信息。从Airflow2.0开始,所有PythonOperator调用的函数会自动接收kwargs作为上下文,无需显式启用provide_context。
注意provide_context仅用于PythonOperator操作符(包括其子类比如BranchPythonOperator),像其他操作符比如BranchOperator、DummyOperator不需要这个参数,因为它们并不使用Python函数,如果是自定义的操作符,可以手动管理是否需要传递上下文。
context与kwargs
两者都可以用于访问任务执行时的上下文信息
def my_task_function(context):
execution_date = context['execution_date']
print(f"Execution date: {execution_date}")
def my_task_function(**kwargs):
execution_date = kwargs.get('execution_date')
print(f"Execution date: {execution_date}")
context属于Airflow自带参数,作为单个dict参数进行传递,包含了execution_date、dag、task_instance等调度相关信息,包括dag传入的params也在其中。访问需要通过类似context('params')
或者context.get('params')
的方式去访问。
python_callable
python_callable是PythonOperator和BranchPythonOperator等操作符的一个关键参数,用于指定一个调用的Python函数,这个函数可以通过op_kwargs和op_args传递参数,也可以通过**kwargs来接受上下文的对象,前者是在task内部定义,后者是由其他task传递或者dag定义的params。
使用示例
基本使用:
def my_task_function():
print("This is my task logic!")
with DAG(
...
) as dag:
my_task = PythonOperator(
task_id='my_task',
python_callable=my_task_function # 指定任务逻辑
)
传递参数:
def my_task_function(param1, param2):
print(f"Param1: {param1}, Param2: {param2}")
my_task = PythonOperator(
task_id='my_task',
python_callable=my_task_function,
op_args=['value1'], # 位置参数
op_kwargs={'param2': 'value2'} # 关键字参数
)
使用上下文:
def my_task_function(**kwargs):
execution_date = kwargs['execution_date']
print(f"Execution date: {execution_date}")
my_task = PythonOperator(
task_id='my_task',
python_callable=my_task_function
)
op_kwargs
op_kwargs参数用于向python_callable指定的函数传递关键字参数,以字典的形式进行传递,任务运行时Airfliow会将其内的键值对解包为关键字参数并传递给python_callable。
使用示例
def my_task_function(param1, param2): # 这里可以直接通过键来调用op_kwargs定义的参数值
print(f"Param1: {param1}, Param2: {param2}")
with DAG(
...
) as dag:
my_task = PythonOperator(
task_id='my_task',
python_callable=my_task_function,
op_kwargs={
'param1': 'value1',
'param2': 'value2'
}
)
当需要同时使用上下文和op_kwargs时:
def my_task_function(param1, param2, **kwargs):
execution_date = kwargs['execution_date']
print(f"Param1: {param1}, Param2: {param2}, Execution Date: {execution_date}")
my_task = PythonOperator(
task_id='my_task',
python_callable=my_task_function,
op_kwargs={
'param1': 'value1',
'param2': 'value2'
}
)
op_args
op_args参数用于向python_callable指定的函数传递位置参数,以列表的形式进行传递,这是它与op_kwargs的区别之一,在任务运行时,Airflow会将op_args中的值按顺序传递给python_callable函数,所以使用时要注意参数的位置。
使用示例
def my_task_function(param1, param2): # 这里会按顺序获得op_args中的参数
print(f"Param1: {param1}, Param2: {param2}")
with DAG(
...
) as dag:
my_task = PythonOperator(
task_id='my_task',
python_callable=my_task_function,
op_args=['value1', 'value2'] # 传递位置参数
)
如果需要与上下文结合使用也是通过**kwargs来传递:
def my_task_function(param1, param2, **kwargs):
execution_date = kwargs['execution_date']
print(f"Param1: {param1}, Param2: {param2}, Execution Date: {execution_date}")
my_task = PythonOperator(
task_id='my_task',
python_callable=my_task_function,
op_args=['value1', 'value2'] # 传递位置参数
)
op_args和op_kwargs两者都可以用于进行参数的传递,只不过前者是按顺序来接收参数,而后者是按字典键来接收参数,具体使用时依据实际情况来选择。
trigger_rule
trigger_rule是用于控制任务何时被触发的规则。可以在任何 Airflow 操作符中使用,是所有操作符的通用属性。默认情况下任务会在所有上游任务成功时触发(all_success),该参数常用于不同分支任务的操作中。
使用示例
task = PythonOperator(
task_id = 'example_task',
python_callable = my_function,
trigger_rule = 'all_success'
)
以下是所有可用的状态:
all_success
task会在所有上游任务成功时触发,属于默认状态,适用绝大多数任务,但是上游依赖于多个任务时(比如上游使用了BranchPythonOperator
),容易出现随着个别分支任务的一起失败或跳过的情况。all_failed
task会在所有上游任务失败时触发,用于处理上游任务全部失败的情况,比如发送警报邮件或者执行补救措施。all_done
task会在所有上游任务完成时触发(无论成功或失败或跳过等其他情况),用于在所有上游任务完成后再执行的任务,比如清理操作,或者上游使用了BranchPythonOperator
需要等待所有分支执行完毕后再进行的操作。one_success
task会在至少一个上游任务成功时触发,用于只需要一个上游任务成功即可继续执行的情况。one failed
task会在至少一个上游任务失败时触发,用于在任何一个上游任务失败时执行的任务,比如发送警报邮件。none_failed
task会在没有上游任务失败时触发(所有上游任务成功或者跳过),用于在需要确保没有失败的情况下继续执行的任务。none_failed_or_skipped
task会在没有上游任务失败或跳过时触发,用于在需要确保所有上游任务成功的情况下继续执行的任务。none_skipped
任务会在没有上游任务跳过时触发(即所有的上游任务成功或失败),适用于需要确保所有上游任务执行的情况下继续执行的任务。dummy
任务会无条件立即触发,无需考虑上游任务的状态,适用于调试或者测试任务以及不依赖于任何上游任务的独立任务,注意这里是不依赖上游任务的状态,并不是不依赖上游任务,即使上游任务未完成,只要调度器到达就会执行,而all_done
参数需要依赖于上游任务的状态(已完成)来执行。
速查表
Trigger Rule | 描述 |
---|---|
all_success (默认) | 所有上游任务成功时触发 |
all_failed | 所有上游任务失败时触发 |
all_done | 所有上游任务完成(无论成功或失败)时触发 |
one_success | 至少一个上游任务成功时触发 |
one_failed | 至少一个上游任务失败时触发 |
none_failed | 没有上游任务失败时触发 |
none_failed_or_skipped | 没有上游任务失败或被跳过时触发 |
none_skipped | 没有上游任务被跳过时触发 |
dummy | 无条件立即触发 |
wait_for_completion
wait_for_completion是TriggerDagRunOperator操作符的参数,用于控制当前任务是否需要等待被触发的DAG完成后再继续执行,默认值为Flase,即不等待触发的目标DAG完成,适用于在触发的目标DAG运行结果对当前任务无影响的时候使用。
当触发的DAG执行结果会影响任务的后续逻辑时,可以设置为True,此时目标DAG如果运行成功,当前任务状态也会变为成功,如果目标DAG运行失败,当前任务状态变为失败。
使用示例
trigger_dag_task = TriggerDagRunOperator(
task_id='trigger_dag_task',
trigger_dag_id='target_dag',
wait_for_completion=True # 等待目标 DAG 完成
)
sla
sla(Service Level Agreement) 用于定义任务的服务级别协议时间,即任务必须在指定的时间内完成,如果未完成则Airflow会触发SLA违规(SLA Miss)事件:Airflow会在Web UI中显示SLA Miss信息,如果配置了SLA Miss通知比如电子邮件,Airflow会发送通知。
注意SLA Miss仅用于监控和通知,并不影响任务的完成状态,即使任务违反了SLA,状态仍然可以是成功或者失败等。
使用示例
def my_task_function():
print("Task is running!")
with DAG(
...
) as dag:
my_task = PythonOperator(
task_id='my_task',
python_callable=my_task_function,
sla=timedelta(minutes=30) # 任务必须在 30 分钟内完成
)