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
{{ ti.xcom_pull(...) }}
などのテンプレートは、テンプレートをサポートするパラメーター内でのみ使用できます。そうしないと、実行前にレンダリングされません。 PythonOperator および BashOperator のtemplate_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,
質問と回答の両方を支持しましたが、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
は両方の機能に必要ですか?この回答を明確にするための編集は大歓迎です!
同じコードを使用し、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