166 lines
4.8 KiB
Python
166 lines
4.8 KiB
Python
# 导入 DAG 类,用于定义工作流
|
||
from airflow import DAG
|
||
|
||
# 导入 PythonOperator:执行普通的 Python 函数
|
||
# 导入 BranchPythonOperator:根据 Python 函数的返回值选择执行分支
|
||
from airflow.operators.python import PythonOperator, BranchPythonOperator
|
||
|
||
# 导入 DummyOperator:空操作任务,用于组织任务依赖关系
|
||
from airflow.operators.dummy import DummyOperator
|
||
|
||
# 导入 TriggerRule:用于设置任务的触发规则
|
||
from airflow.utils.trigger_rule import TriggerRule
|
||
|
||
# 导入 datetime,用于设置 DAG 的开始日期
|
||
from datetime import datetime
|
||
|
||
# 导入 random,用于生成随机数
|
||
import random
|
||
|
||
|
||
# ==================== 1. 定义分支选择函数 ====================
|
||
|
||
def choose_branch(**kwargs):
|
||
"""
|
||
分支选择函数。
|
||
|
||
BranchPythonOperator 执行该函数,
|
||
根据函数的返回值决定执行哪个下游任务。
|
||
|
||
**kwargs:接收 Airflow 自动传入的任务上下文参数。
|
||
"""
|
||
|
||
# 随机生成 1~3 之间的整数,包含 1 和 3
|
||
random_number = random.randint(1, 3)
|
||
|
||
# 将生成的随机数输出到任务日志中,方便调试
|
||
print(f'Random number generated: {random_number}')
|
||
|
||
# 根据随机数选择执行的分支
|
||
# 注意:返回值必须是下游任务的 task_id
|
||
|
||
if random_number == 1:
|
||
return 'task_a' # 随机数为 1,选择 A 分支
|
||
|
||
elif random_number == 2:
|
||
return 'task_b' # 随机数为 2,选择 B 分支
|
||
|
||
else:
|
||
return 'task_c' # 随机数为 3,选择 C 分支
|
||
|
||
|
||
# ==================== 2. 定义普通任务函数 ====================
|
||
|
||
def print_task(task_name):
|
||
"""
|
||
普通任务函数。
|
||
|
||
task_name:任务名称,用于区分不同的分支任务。
|
||
"""
|
||
|
||
# 输出当前执行的任务名称
|
||
print(f'Executing {task_name}')
|
||
|
||
|
||
# ==================== 3. 创建 DAG 工作流 ====================
|
||
|
||
with DAG(
|
||
# DAG 的唯一标识符
|
||
dag_id='branch_example',
|
||
|
||
# 设置调度周期为每天执行一次
|
||
schedule_interval='@daily',
|
||
|
||
# 设置 DAG 开始日期
|
||
start_date=datetime(2026, 10, 1),
|
||
|
||
# 开启历史补跑
|
||
# Airflow 会根据调度规则处理开始日期之后符合条件的历史调度周期
|
||
catchup=True,
|
||
|
||
# 设置 DAG 标签,方便在 Airflow 页面中查找
|
||
tags=['demo']
|
||
|
||
) as dag:
|
||
|
||
# ==================== 4. 定义分支选择任务 ====================
|
||
|
||
branching_task = BranchPythonOperator(
|
||
# 任务 ID
|
||
task_id='branching_task',
|
||
|
||
# 指定执行的 Python 函数
|
||
# 函数的返回值决定执行哪个下游分支
|
||
python_callable=choose_branch,
|
||
)
|
||
|
||
# ==================== 5. 定义 A 分支任务 ====================
|
||
|
||
task_a = PythonOperator(
|
||
# 任务 ID,必须与分支函数返回的名称一致
|
||
task_id='task_a',
|
||
|
||
# 使用 lambda 创建一个无参数函数
|
||
# 执行任务时,调用 print_task('Task A')
|
||
python_callable=lambda: print_task('Task A'),
|
||
)
|
||
|
||
# ==================== 6. 定义 B 分支任务 ====================
|
||
|
||
task_b = PythonOperator(
|
||
# B 分支的任务 ID
|
||
task_id='task_b',
|
||
|
||
# 执行时打印 Task B
|
||
python_callable=lambda: print_task('Task B'),
|
||
)
|
||
|
||
# ==================== 7. 定义 C 分支任务 ====================
|
||
|
||
task_c = PythonOperator(
|
||
# C 分支的任务 ID
|
||
task_id='task_c',
|
||
|
||
# 执行时打印 Task C
|
||
python_callable=lambda: print_task('Task C'),
|
||
)
|
||
|
||
# ==================== 8. 定义结束任务 ====================
|
||
|
||
end_task = DummyOperator(
|
||
# 结束任务的 ID
|
||
task_id='end_task',
|
||
|
||
# 设置触发规则:
|
||
# 所有上游任务中没有失败的任务,并且至少有一个上游任务成功,
|
||
# 当前任务就可以执行。
|
||
#
|
||
# 因为分支选择会把未选中的任务标记为 skipped,
|
||
# 所以不能简单使用默认的 all_success,
|
||
# 否则 end_task 可能因为存在 skipped 上游任务而被跳过。
|
||
trigger_rule=TriggerRule.NONE_FAILED_MIN_ONE_SUCCESS,
|
||
)
|
||
|
||
# ==================== 9. 设置任务依赖关系 ====================
|
||
|
||
# 分支任务执行完成后,根据返回值选择一个分支:
|
||
#
|
||
# 返回 'task_a' -> 执行 task_a
|
||
# 返回 'task_b' -> 执行 task_b
|
||
# 返回 'task_c' -> 执行 task_c
|
||
#
|
||
# 未被选中的分支会被标记为 skipped。
|
||
#
|
||
# 被选中的分支执行完成后,end_task 在满足触发规则时执行。
|
||
|
||
branching_task >> [task_a, task_b, task_c] >> end_task
|
||
|
||
# 上面的依赖关系等价于:
|
||
#
|
||
# branching_task >> task_a
|
||
# branching_task >> task_b
|
||
# branching_task >> task_c
|
||
#
|
||
# task_a >> end_task
|
||
# task_b >> end_task
|
||
# task_c >> end_task |