我正在尝试从XCOM变量生成一组动态任务。在XCOM中,我存储一个列表,我想使用列表中的每个元素来动态创建下游任务。
我的用例是,我有一个上游操作员,该操作员检查sftp服务器中的文件并返回符合特定条件的文件名列表。我想为返回的每个文件名创建动态下游任务。
我已将其简化为以下内容,虽然它可以正常工作,但我感觉它不是惯用的气流解决方案。在我的用例中,我将编写一个从python运算符调用的python函数,该运算符将从xcom中获取值并返回它,而不是使用pusher函数。
我了解,虽然我可以创建一个将两者结合起来的自定义运算符,但我认为创建一个一次性运算符不是一个好习惯,我希望有另一种解决方案。
from airflow.operators.python_operator import PythonOperator
from airflow.operators.bash_operator import BashOperator
from airflow import DAG
from datetime import datetime, timedelta
default_args = {
"owner": "test",
"depends_on_past": False,
"start_date": datetime(2018, 10, 27),
"email": ["test@mctest.com"],
"email_on_failure": False,
"email_on_retry": False,
"email_on_success": False,
"retries": 0,
"provide_context": True
}
dag = DAG("test", default_args=default_args, schedule_interval="@daily", catchup=False)
def pusher(**context):
return ['a', 'b', 'c', 'd', 'e']
pusher_task = PythonOperator(
task_id='pusher_task',
dag=dag,
python_callable=pusher
)
def bash_wrapper(task, **context):
return BashOperator(
task_id='dynamic'+task,
dag=dag,
bash_command='date'
)
end = BashOperator(task_id='end', dag=dag, bash_command='echo task has ended')
pusher_task >> [bash_wrapper(task) for task in pusher()] >> end
答案 0 :(得分:2)
我不会做您想达到的目标,主要是因为:
即使您使用类似以下内容的方法来访问由某些上游任务生成的XCOM值:
from airflow.models import TaskInstance
from airflow.utils.db import provide_session
dag = DAG(...)
@provide_session
def get_files_list(session):
execution_date = dag.previous_schedule(datetime.now())
// Find previous task instance:
ti = session.query(TaskInstance).filter(
TaskInstance.dag_id == dag.dag_id,
TaskInstance.execution_date == execution_date,
TaskInstance.task_id == upstream_task_id).first()
if ti:
files_list = ti.xcom_pull()
if files_list:
return files_list
// Return default state:
return {...}
files_list = get_files_list()
// Generate tasks based on upstream task state:
task = PythonOperator(
...
xcom_push=True,
dag=dag)
但这会表现得很奇怪,因为DAG解析和任务执行未按照您希望的方式进行同步。
如果您要这样做的主要原因是并行处理文件,我将有一些静态处理任务(由所需的并行性确定),这些任务从上游任务的XCOM值读取文件列表并在其中的相关部分上进行操作该列表。
另一个选择是使用某些框架(例如Apache Spark)并行化文件处理。
答案 1 :(得分:0)