Solutions — Homework 04
Lesson 04 · Data Engineering with Python
Task 1 — Add a third task: summarize
Add the following callable and operator to gharchive_hourly.py. The import for
pandas is deferred inside the function body — not at module scope — to keep parse
time fast.
def _summarize(**context) -> None:
import pandas as pd
df = pd.read_parquet("/opt/airflow/sample-pipeline/data/2026-05-01-12.parquet")
print(df.groupby("event_type").size().sort_values(ascending=False).head(5).to_string())
# inside the DAG context (after the existing operators):
summarize = PythonOperator(task_id="summarize", python_callable=_summarize)
extract >> transform >> summarize
Common mistake
Importing pandas at module scope (import pandas as pd at the top of
the file) works, but adds ~100 ms to every scheduler heartbeat. Over a deployment with dozens
of DAGs, this adds up. Keep heavy imports inside the function body.
Task 2 — Bash operator practice: cleanup
Import BashOperator and add the fourth task. Note: the import can go at the top of
the file alongside the existing Airflow imports — BashOperator itself is lightweight
to import.
from airflow.operators.bash import BashOperator
# inside the DAG context:
cleanup = BashOperator(
task_id="cleanup",
bash_command="du -sh /opt/airflow/sample-pipeline/data/",
)
extract >> transform >> summarize >> cleanup
Common mistake
Using a host path (e.g., data-engineering/sample-pipeline/data/) instead of the
container path. BashOperator runs inside the Airflow worker container — paths must
reference container mount points. The docker-compose.yaml mounts the
sample-pipeline/ directory at /opt/airflow/sample-pipeline, so that
is the correct base path.
Task 3 — Read the parse log
A sample line from the scheduler logs:
[2026-05-26 09:10:01] {dag_processing.py:712} INFO - Processing dags/gharchive_hourly.py took 0.34 seconds
Your number will vary. On a clean laptop with deferred imports, expect 0.1–0.5 seconds. If you see > 1 second, check whether you have any heavy imports at module scope.
Common mistake
Confusing parse time with task runtime. Parse time is the time the scheduler
spends importing the DAG file every 30 seconds — it is purely the cost of Python import
statements. Task runtime is how long the actual callable takes to execute (downloading a file,
running a transformation). These are completely separate metrics and appear in different log
locations: parse time in airflow-scheduler logs, task runtime in the task instance
logs accessible from the Grid view.
Lesson 05 makes this DAG scheduled and replayable across past time windows. Instead of a hardcoded hour, each run will process its own data interval — making the pipeline genuinely useful and backfillable.