liveBook · Manning

Generator

As explained in Data Pipelines with Apache Airflow, Second Edition

A generator is a Python iterable that produces values incrementally rather than materializing them all at once.

A generator is a Python iterable that produces values incrementally instead of materializing them all at once. In an API data pipeline, it can hide pagination and expose individual rating records through one interface. section 9.1.2

A paginated generator separates fetching mechanics from the code consuming records:

  • Request a page with offset and limit parameters. section 9.1.2
  • Raise an error for unsuccessful responses and decode the JSON payload. section 9.1.2
  • Use yield from to expose each record from the current page. section 9.1.2
  • Fetch the next page only after the current page’s records have been exhausted. section 9.1.2
Listing 9.3 Helper function for handling pagination
def _get_with_pagination(session, url, params, batch_size=100):
   """
   Fetches records using a GET request with given URL/params,
   taking pagination into account.
   """

   offset = 0                                 #1
   total = None                                #1
   while total is None or offset < total:     #2
       response = session.get(
           url,
           params={
               **params,
               **{"offset": offset, "limit": batch_size} #3
           }
       )                                
       response.raise_for_status()
       response_json = response.json()   #4

       yield from response_json["result"]    #5

       offset += batch_size                  #6
       total = response_json["total"]         #6

A pagination helper yields records while tracking offsets, totals, response validation, and page size. section 9.1.2

Checking whether any ratings exist

A custom Airflow sensor can call next on the generator with batch_size=1. If a record is produced, the sensor returns True; if the generator is empty and raises StopIteration, it returns False and waits for another check. section 9.4

Listing 9.29 Implementing the poke method
class MovielensRatingsSensor(BaseSensorOperator):
   def poke(self, context:Context):
       hook = MovielensHook(self._conn_id)

       try:
           next(                  #1
               hook.get_ratings(
                   start_date=self._start_date,
                   end_date=self._end_date,
                   batch_size=1
               )
           )
           self.log.info(
               f"Found ratings for {self._start_date} to {self._end_date}"
           )
           return True           #2
       except StopIteration:        #3
           self.log.info(
               f"Didn't find any ratings for {self._start_date} "
               f"to {self._end_date}, waiting..."
           )
           return False              #3
       finally:
           hook.close()            #4

The sensor implementation demonstrates generator consumption, StopIteration handling, logging, and hook cleanup. section 9.4

How Data Pipelines with Apache Airflow, Second Edition covers it

How deep it goes
Explains generator creation with yield from, deferred page fetching, and StopIteration handling without covering generator internals.
Examples
Demonstrates paginated MovieLens ratings retrieval and a sensor that tests for one available record.
What it assumes
Assumes familiarity with Python functions, HTTP responses, and Airflow hooks or sensors.
What you can do after
Apply it via Python generators to stream paginated API records or test whether a result exists without fetching everything.
How it connects
Connects generators to Python iterables, API pagination, HTTP requests, and Airflow sensors.

Also explained in

Compare how 12 books explain generator →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Data Pipelines with Apache Airflow, Second Edition. The section links point to the parts of the book it draws on.