我正在尝试在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'
答案 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()
返回的值会经常变化,那么task
中dag
的个数也会不断变化。这可能会导致不可预测的行为(您应该进行大量研究,但我对此并不满意)
我建议您重新查看整个任务工作流程,并精简为一个
-task
的数量和
-DAG
的结构
提前知道(在 dag定义文件的执行时)。当然,您可以遍历json
文件/ SQL
查询的结果(例如前面提到的SQLAlchemy
事物)等,以产生实际的task
,但是该文件/数据库/不应该经常更改的内容。
请理解,仅迭代列表以生成task
并不成问题;不可能根据DAG
upstream
的结果来确定task
的结构。例如,您无法基于上游任务在运行时计算n的值,在task
中创建n个DAG
。
所以这不可能
但这是可能的(包括您要实现的目标;即使您的工作方式似乎不是一个好主意)