在气流中子标签创建时访问父dag上下文?

时间:2019-02-18 10:49:52

标签: airflow apache-airflow-xcom

我正在尝试在subdag创建时从父级dag访问一些xcom数据,我正在搜索以在Internet上实现此功能,但没有找到任何东西。

def test(task_id):
    logging.info(f' execution of task {task_id}')


def load_subdag(parent_dag_id, child_dag_id, args):
    dag_subdag = DAG(
        dag_id='{0}.{1}'.format(parent_dag_id, child_dag_id),
        default_args=args,
        schedule_interval="@daily",
    )
    with dag_subdag:
        r = DummyOperator(task_id='random')

        for i in range(r.xcom_pull(task_ids='take_Ana', key='the_message', dag_id=parent_dag_id)):
            t = PythonOperator(
                task_id='load_subdag_{0}'.format(i),
                default_args=args,
                python_callable=print_context,
                op_kwargs={'task_id': 'load_subdag_{0}'.format(i)},
                dag=dag_subdag,
            )

    return dag_subdag

load_tasks = SubDagOperator(
        task_id='load_tasks',
        subdag=load_subdag(dag.dag_id,
                           'load_tasks', args),
        default_args=args,
    )

使用我的代码获取了此错误

1  | Traceback (most recent call last):
airflow_1  |   File "/usr/local/lib/python3.6/site-packages/airflow/models.py", line 374, in process_file
airflow_1  |     m = imp.load_source(mod_name, filepath)
airflow_1  |   File "/usr/local/lib/python3.6/imp.py", line 172, in load_source
airflow_1  |     module = _load(spec)
airflow_1  |   File "<frozen importlib._bootstrap>", line 684, in _load
airflow_1  |   File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
airflow_1  |   File "<frozen importlib._bootstrap_external>", line 678, in exec_module
airflow_1  |   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
airflow_1  |   File "/app/dags/airflow_dag_test.py", line 75, in <module>
airflow_1  |     'load_tasks', args),
airflow_1  |   File "/app/dags/airflow_dag_test.py", line 55, in load_subdag
airflow_1  |     for i in range(r.xcom_pull(task_ids='take_Ana', key='the_message', dag_id=parent_dag_id)):
airflow_1  | TypeError: xcom_pull() missing 1 required positional argument: 'context'

1 个答案:

答案 0 :(得分:1)

错误很简单:您缺少xcom_pull()方法所需的context参数。但是,您确实不能仅仅创建context来传递给此方法。这是Python传递给Airflow(所有BaseOperator的父类)之类的锚定方法之类的Operator dictionary

换句话说,context仅在实际执行Operator时可用,而在DAG定义期间不可用。这是有道理的,因为在Airflow分类中,xcom是实时{em>的task之间的通信机制:他们正在运行时。


但是最终,Xcom和其他所有Airflow模型一样,都保留在后端元数据库中。因此,您当然可以从那里直接检索它(显然只有过去运行的task的XCOM)。虽然我没有代码片段,但是您可以看看pre_execute() and execute(),他们使用SQLAlchemy ORM来处理模型和后端数据库。要了解,这意味着每次解析DAG定义文件时都会向您的后端数据库触发查询,发生得很快。


有用的链接


EDIT-1

查看您的代码段后,我感到震惊。假设xcom_pull()返回的值会经常变化,那么taskdag个数也会不断变化。这可能会导致不可预测的行为(您应该进行大量研究,但我对此并不满意)

我建议您重新查看整个任务工作流程,并精简为一个  -task的数量和  -DAG的结构 提前知道(在 dag定义文件执行时)。当然,您可以遍历json文件/ SQL查询的结果(例如前面提到的SQLAlchemy事物)等,以产生实际的task,但是该文件/数据库/不应该经常更改的内容。


请理解,仅迭代列表以生成task并不成问题;不可能根据DAG upstream的结果来确定task的结构。例如,您无法基于上游任务在运行时计算n的值,在task中创建n个DAG


所以这不可能

但这是可能的(包括您要实现的目标;即使您的工作方式似乎不是一个好主意)