如何使用Python在气流中成功触发另一个DAG?

如何使用Python在气流中成功触发另一个DAG?,python,python-3.x,airflow,directed-acyclic-graphs,airflow-scheduler,Python,Python 3.x,Airflow,Directed Acyclic Graphs,Airflow Scheduler,我有一个python DAG父作业和DAG子作业。每日运行的父作业任务成功完成后,应触发子作业中的任务。如何添加外部作业触发器 我的代码 from datetime import datetime, timedelta from airflow import DAG from airflow.operators.postgres_operator import PostgresOperator from utils import FAILURE_EMAILS yesterday = datet

我有一个python DAG
父作业
和DAG
子作业
。每日运行的
父作业
任务成功完成后,应触发
子作业
中的任务。如何添加外部作业触发器

我的代码

from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.postgres_operator import PostgresOperator
from utils import FAILURE_EMAILS

yesterday = datetime.combine(datetime.today() - timedelta(1), datetime.min.time())


default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': yesterday,
    'email': FAILURE_EMAILS,
    'email_on_failure': False,
    'email_on_retry': False,
    'retries': 1,
    'retry_delay': timedelta(minutes=5)
}

dag = DAG('Child Job', default_args=default_args, schedule_interval='@daily')

execute_notebook = PostgresOperator(
  task_id='data_sql',
  postgres_conn_id='REDSHIFT_CONN',
  sql="SELECT * FROM athena_rs.shipments limit 5",
  dag=dag
)

我相信你正在寻找,在一个更大的Dag中运行一个Dag。 请注意,像下面的示例中那样创建许多子DAG会很快变得混乱,因此我建议将每个子DAG拆分为一个文件,然后导入到主文件中

subdag操作符使用简单,您需要提供Id、subdag(子对象)和dag(父对象)

答案已经出来了。下面是演示代码:

父dag:

from datetime import datetime
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator

default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': datetime(2020, 4, 29),
}

dag = DAG('Parent_dag', default_args=default_args, schedule_interval='@daily')

leave_work = DummyOperator(
    task_id='leave_work',
    dag=dag,
)
cook_dinner = DummyOperator(
    task_id='cook_dinner',
    dag=dag,
)

leave_work >> cook_dinner
儿童dag:

from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators.sensors import ExternalTaskSensor

default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': datetime(2020, 4, 29),
}

dag = DAG('Child_dag', default_args=default_args, schedule_interval='@daily')

# Use ExternalTaskSensor to listen to the Parent_dag and cook_dinner task
# when cook_dinner is finished, Child_dag will be triggered
wait_for_dinner = ExternalTaskSensor(
    task_id='wait_for_dinner',
    external_dag_id='Parent_dag',
    external_task_id='cook_dinner',
    start_date=datetime(2020, 4, 29),
    execution_delta=timedelta(hours=1),
    timeout=3600,
)

have_dinner = DummyOperator(
    task_id='have_dinner',
    dag=dag,
)
play_with_food = DummyOperator(
    task_id='play_with_food',
    dag=dag,
)

wait_for_dinner >> have_dinner
wait_for_dinner >> play_with_food
图像:

达吉斯

父母

童装

如前所述,我在此添加一个片段,描述使用
TriggerDagRunOperator
(与
ExternalTaskSensor
的基于轮询的触发相反)的反应性触发

请注意,代码片段仅供参考;它还没有经过测试


注意事项/参考资料


这是否回答了您的问题@幸运的是,这个例子显示了一个任务另一个dag在另一个任务中触发另一个任务。这里是我所想的他所看到的,一个DAG的完成完全触发了下一个DAG。如果你能给出一个例子,那就太好了。我强烈建议使用来执行反应式触发,而不是
ExternalTaskSensor
来执行基于轮询的触发triggering@y2k-shubham,如果你能像下面写的那样写一个例子,它也将为其他人学习。我也面临同样的问题。@pankaj我添加了一个描述
TriggerDagRunOperator
用法的答案,谢谢。我在找另一个案子。也许我把它弄糊涂了。父Dag基本上是另一个作业,“子Dag”是另一个作业。在成功完成第一份工作后,我想成为“触发孩子”。如果你能帮我的话,那就太好了nice@aeapen你所说的工作是什么意思?它是一项任务,还是一个任务?这段代码正是您所描述的。。。要匹配您的案例,您唯一要做的就是将父Dag添加到此管道的末尾。我将更新dag以演示它。。。但是这种思维方式不是独立地拥有两个不同的DAG,而是嵌套DAG,父->子。。。这对我来说更有意义。另一种方法是使用ExternalTaskSensor操作符从另一个DAG触发一个DAG,这在我的示例中更容易混淆opinion@aeapen我更新了我的解决方案,这更符合您的需要吗?我的意思是作业是一个DAG,它包含多个任务。我尝试了这个方法,但发现超时错误。
[MainThread]INFO AIFLOW.task.OPERATOR-[2020-05-01 09:51:14444]{{external_task_sensor.py:115}}在2020-04-29T23:00:00+00:00上戳RS_Input_CLEANING.events_Input_sql。。。[MainThread]ERROR.task-[2020-05-01 09:51:14508]{{{taskinstance.py:1088}}Snap。时间到了。回溯(最近一次调用):文件“/usr/local/lib/python3.7/site packages/afflow/models/taskinstance.py”,第955行,在_run\u raw\u task result=task\u copy.execute(context=context)
中,如果父Dag已处于成功状态。如果手动触发,子Dag将运行?您可能需要打开另一个问题并发布完整日志。但要回答您的问题,是的,如果
RS\u Input\u cleaning.events\u Input\u sql
按时完成,子dag将自动运行父dag的最后一个任务需要2小时才能完成。这就是超时的原因,因为我们给了超时1小时。是的,增加
超时时间。现在它被设置为3600秒,也就是1小时。它起作用了。这是我的孩子在父母身上取得的成功。我仍然有疑问。我孩子的dag是
dag=dag('child',default\u args=default\u args,catchup=False,schedule\u interval='@daily')
。我的父母DAG计划在早上8:30跑步。子作业在父DAG完成后在上午8:30运行,并且在上午12:00再次运行。我在DAG中丢失了一些内容。@aeapen您可能希望将您的子DAG的
计划间隔设置为
None
。这样它就不会被气流自动驱动;只有在完成父DAG时才会触发
from datetime import datetime
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator

default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': datetime(2020, 4, 29),
}

dag = DAG('Parent_dag', default_args=default_args, schedule_interval='@daily')

leave_work = DummyOperator(
    task_id='leave_work',
    dag=dag,
)
cook_dinner = DummyOperator(
    task_id='cook_dinner',
    dag=dag,
)

leave_work >> cook_dinner
from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators.sensors import ExternalTaskSensor

default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': datetime(2020, 4, 29),
}

dag = DAG('Child_dag', default_args=default_args, schedule_interval='@daily')

# Use ExternalTaskSensor to listen to the Parent_dag and cook_dinner task
# when cook_dinner is finished, Child_dag will be triggered
wait_for_dinner = ExternalTaskSensor(
    task_id='wait_for_dinner',
    external_dag_id='Parent_dag',
    external_task_id='cook_dinner',
    start_date=datetime(2020, 4, 29),
    execution_delta=timedelta(hours=1),
    timeout=3600,
)

have_dinner = DummyOperator(
    task_id='have_dinner',
    dag=dag,
)
play_with_food = DummyOperator(
    task_id='play_with_food',
    dag=dag,
)

wait_for_dinner >> have_dinner
wait_for_dinner >> play_with_food
from typing import List

from airflow.models.baseoperator import BaseOperator
from airflow.models.dag import DAG
from airflow.operators.dagrun_operator import TriggerDagRunOperator
from airflow.utils.trigger_rule import TriggerRule

# DAG object
my_dag: DAG = DAG(dag_id='my_dag',
                  start_date=..)
..
# a list of 'tail' tasks: tasks that have no downstream tasks
tail_tasks_of_first_dag: List[BaseOperator] = my_magic_function_that_determines_all_tail_tasks(..)
..

# our trigger task
my_trigger_task: TriggerDagRunOperator = TriggerDagRunOperator(dag=my_dag,
                                                               task_id='my_trigger_task',
                                                               trigger_rule=TriggerRule.ALL_SUCCESS,
                                                               external_dag_id='id_of_dag_to_be_triggered')
# our trigger task should run when all 'tail' tasks have completed / succeeded
tail_tasks_of_first_dag >> my_trigger_task