我试图通过XCom将一个字符串列表从一个任务传递到另一个任务,但我似乎无法将推送列表解释为列表。
例如,当我在blah
中运行的某个函数ShortCircuitOperator
中执行此操作时:
paths = ['gs://{}/{}'.format(bucket, obj) for obj in my_list]
kwargs['ti'].xcom_push(key='return_value', value=full_paths)
然后我想使用这样的列表作为运算符的参数。例如,
run_task_after_blah = AfterBlahOperator(
task_id='run-task-after-blah',
...,
input_paths="{{ ti.xcom_pull(task_ids='find-paths') }}",
...,
)
我希望input_paths
等于paths
,但它不会,因为渲染发生在第一次然后分配,有些模板渲染将xcom_pull
返回转换为 stringified 列表(之后我的AfterBlahOperator
插入将其指定为JSON中元素的值。
我尝试将paths
连接到由一些分隔符分隔的一个字符串中并将其推送到XCom然后在从XCom拉出时将其拆分但是当XCom首先被渲染时,我得到了split函数时的> stringified 列表,如果paths
函数应用于参数,则split
的原始连接字符串(如{{1 }}
当可以进一步处理提取的值时,XCom似乎非常适合将单个值用作任务参数或多个值,但不能将多个值转换为一个'作为任务的参数。
有没有办法做到这一点,而无需编写一个精确返回这样的字符串列表的额外函数? 或者我可能过多地滥用XCom,但Airflow中有许多运算符将元素列表作为参数(例如,通常是多个文件的完整路径,这是前一个任务的结果,因此事先不知道)。 / p>
答案 0 :(得分:3)
Jinja呈现字符串,因此如果您通过模板获取XCom,它将始终是一个字符串。相反,您需要获取可以访问TaskInstance
对象的XCom。像这样:
class AfterBlahOperator(BaseOperator):
def __init__(self, ..., input_task_id, *args, **kwargs):
...
self.input_task_id = input_task_id
super(AfterBlahOperator, self).__init__(*args, **kwargs)
def execute(self, context):
input_paths = context['ti'].xcom_pull(task_ids=self.input_task_id)
for path in input_paths:
...
这类似于您在PythonOperator
中提取的方式,XCom docs提供了一个示例。
请注意,您仍然可以支持单独的input_paths
参数,以便在DAG中对其进行硬编码时,您只需要额外检查以查看从哪个参数中读取值。
答案 1 :(得分:0)
在eval(input_paths)
的{{1}}方法中调用AfterBlahOperator
。这样,可以将字符串化列表转换回列表
execute