web-dev-qa-db-ja.com

エアフロー-xcom変数をPython関数に渡す方法

BashOperatorによって返される変数を参照する必要があります。これは間違っているかもしれませんのでご容赦ください。 task_archive_s3_fileで、get_s3_fileからファイル名を取得する必要があります。タスクは、値の代わりに文字列として{{ ti.xcom_pull(task_ids=submit_file_to_spark) }}を単に出力します。

bash_commandを使用すると、値は正しく印刷されます。

get_s3_file = PythonOperator(
    task_id='get_s3_file',
    python_callable=obj.func_get_s3_file,
    trigger_rule=TriggerRule.ALL_SUCCESS,
    dag=dag)

submit_file_to_spark = BashOperator(
    task_id='submit_file_to_spark',
    bash_command="echo 'hello world'",
    trigger_rule="all_done",
    xcom_Push=True,
    dag=dag)

task_archive_s3_file = PythonOperator(
    task_id='archive_s3_file',
#    bash_command="echo {{ ti.xcom_pull(task_ids='submit_file_to_spark') }}",
    python_callable=obj.func_archive_s3_file,
    params={'s3_path_filename': "{{ ti.xcom_pull(task_ids=submit_file_to_spark) }}" },
    dag=dag)

get_s3_file >> submit_file_to_spark >> task_archive_s3_file
23
luckytaxi

{{ ti.xcom_pull(...) }}などのテンプレートは、テンプレートをサポートするパラメーター内でのみ使用できます。そうしないと、実行前にレンダリングされません。 PythonOperator および BashOperatortemplate_fieldsおよびtemplate_ext属性を参照してください。

したがって、templates_dictは、テンプレートをpython演算子に渡すために使用するものです。

def func_archive_s3_file(**context):
    archive(context['templates_dict']['s3_path_filename'])

task_archive_s3_file = PythonOperator(
    task_id='archive_s3_file',
    dag=dag,
    python_callable=obj.func_archive_s3_file,
    provide_context=True,  # must pass this because templates_dict gets passed via context
    templates_dict={'s3_path_filename': "{{ ti.xcom_pull(task_ids='submit_file_to_spark') }}" })

ただし、XCom値を取得する場合、別の代替方法は、コンテキストを介して利用可能になったTaskInstanceオブジェクトを使用することです。

def func_archive_s3_file(**context):
    archive(context['ti'].xcom_pull(task_ids='submit_file_to_spark'))

task_archive_s3_file = PythonOperator(
    task_id='archive_s3_file',
    dag=dag,
    python_callable=obj.func_archive_s3_file,
    provide_context=True,
28
Daniel Huang

質問と回答の両方を支持しましたが、DAGのPythonOperatorタスク間で小さなデータオブジェクトを渡したいだけのユーザーにとっては、これをもう少し明確にできると思います。この質問と このXComの例 を参照すると、次の解決策が見つかりました。超シンプル:

from airflow.models import DAG
from airflow.operators.python_operator import PythonOperator

DAG = DAG(
  dag_id='example_dag',
  start_date=datetime.now(),
  schedule_interval='@once'
)

def Push_function(**kwargs):
    ls = ['a', 'b', 'c']
    return ls

Push_task = PythonOperator(
    task_id='Push_task', 
    python_callable=Push_function,
    provide_context=True,
    dag=DAG)

def pull_function(**kwargs):
    ti = kwargs['ti']
    ls = ti.xcom_pull(task_ids='Push_task')
    print(ls)

pull_task = PythonOperator(
    task_id='pull_task', 
    python_callable=pull_function,
    provide_context=True,
    dag=DAG)

Push_task >> pull_task

なぜこれが機能するのかわかりませんが、機能します。コミュニティに関するいくつかの質問:

  • ここでtiで何が起こっていますか? **kwargsにはどのように組み込まれていますか?
  • provide_context=Trueは両方の機能に必要ですか?

この回答を明確にするための編集は大歓迎です!

17
Aaron

同じコードを使用し、Startdateなどのような変更されたパラメータ.

import airflow
from datetime import datetime, timedelta
from airflow.models import DAG
from airflow.operators.python_operator import PythonOperator

args = {
    'owner': 'Airflow',
    'start_date': airflow.utils.dates.days_ago(2),
}

DAG = DAG(
  dag_id='simple_xcom',
  default_args=args,
#  start_date=datetime(2019, 04, 21),
  schedule_interval="@daily",
  #schedule_interval=timedelta(1)
)

def Push_function(**context):
    msg='the_message'
    print("message to Push: '%s'" % msg)
    task_instance = context['task_instance']
    task_instance.xcom_Push(key="the_message", value=msg)

Push_task = PythonOperator(
    task_id='Push_task', 
    python_callable=Push_function,
    provide_context=True,
    dag=DAG)

def pull_function(**kwargs):
    ti = kwargs['ti']
    msg = ti.xcom_pull(task_ids='Push_task',key='the_message')
    print("received message: '%s'" % msg)

pull_task = PythonOperator(`enter code here`
    task_id='pull_task', 
    python_callable=pull_function,
    provide_context=True,
    dag=DAG)

Push_task >> pull_task
6
dan