def push_function(ti): ti.xcom_push(key='result', value=42) def pull_function(ti): value = ti.xcom_pull(key='result', task_ids='push_task') print(value) # Assume push_function runs as 'push_task' and pull_function runs as 'pull_task' downstream.
The push_function stores the integer 42 with key 'result'. The pull_function retrieves it using the same key and task id, so it prints 42.
PythonOperator automatically pushes the return value of the Python callable to XCom with the key 'return_value'. This allows downstream tasks to pull it easily.
If 'task_b' runs before 'task_a' finishes, the value won't be available yet. If the key is wrong or 'task_a' never pushed, the pull returns None. All these cause None.
Setting 'task1' upstream of 'task2' ensures 'task1' runs first and pushes the value. 'task2' can then pull it using task_ids='task1'.
XCom is not designed for large data. Best practice is to store big data externally and pass only a small reference or path through XCom to keep performance and reliability.