【问题标题】:Airflow tasks after BranchPythonOperator get skipped unexpectedlyBranchPythonOperator 后的气流任务被意外跳过
【发布时间】:2019-08-05 22:49:21
【问题描述】:

我的 dag 定义如下。尽管flag1flag2 都是y,但不知何故被跳过了。

from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators.python_operator import BranchPythonOperator
import pandas as pd
from itertools import compress



default_args = {
    'owner': 'alex'
    , 'retries': 2
    , 'retry_delay': timedelta(minutes=15)
    , 'depends_on_past': False
    , 'start_date': datetime(2018, 11, 22)
}

dag = DAG(
    'test_dag'
    , catchup = False
    , default_args = default_args
    , schedule_interval = '@daily'
)

task1 = DummyOperator(
        task_id='task1',
        dag=dag,
    )

task2 = DummyOperator(
        task_id='task2',
        dag=dag,
    )

task3 = DummyOperator(
        task_id='task3',
        dag=dag,
    )


# 1 means yes, 0 means no
flag1 = 'y'
flag2 = 'y'
flag3 = 'y'

tasks_name = ['task1', 'task2', 'task3']
flags = [flag1, flag2, flag3]


def generate_branches(tasks_name, flags):
    res = []
    idx = 1
    root_name = 'switch'
    for sub_task, sub_flag in zip(tasks_name, flags):
        tmp_branch_operator = BranchPythonOperator(
            task_id=root_name+str(idx), # switch1, switch2, ...
            python_callable= lambda: sub_task if sub_flag == 'y' else 'None',
            dag=dag,
        )
        res.append(tmp_branch_operator)
        idx += 1
    return res


def set_dependencies(switches, transfer_operators):
    for sub_switch, sub_transfer_operator in zip(switches, transfer_operators):
        sub_switch.set_downstream(sub_transfer_operator)


transfer_operators = [task1, task2, task3]
gen_branches_op = generate_branches(tasks_name, flags)
set_dependencies(gen_branches_op, transfer_operators)

【问题讨论】:

    标签: python python-3.x python-2.x airflow


    【解决方案1】:

    该问题是由 lambda 的后期绑定行为引起的。因为 lambda 在调用时会被计算,所以每次你的 lambda 总是返回列表中的最后一个元素,即task3

    如果你可以查看 switch1 和 switch2 的日志,你会发现它们有以下分支 task3 而不是 task1task2

    为避免这种情况,您可以通过在 generate_branches() 中更改 python_callable 来强制在定义 lambda 时对其进行评估:

    def generate_branches(tasks_name, flags):
        res = []
        idx = 1
        root_name = 'switch'
        for sub_task, sub_flag in zip(tasks_name, flags):
            tmp_branch_operator = BranchPythonOperator(
                task_id=root_name+str(idx), # switch1, switch2, ...
                python_callable=lambda sub_task=sub_task: sub_task if sub_flag == "y", else "None"
                dag=dag,
            )
            res.append(tmp_branch_operator)
            idx += 1
        return res
    

    【讨论】:

    • 尝试了您的解决方案。它适用于标志 = ['y', 'y', 'y']。但是当我将其更改为 ['y', 'n', 'n'] 时,这三个任务都被跳过了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多