Skip to content

← Generators, Iterators and Streaming Data step 4 of 9

Easy Primitives

Build a Pipeline from Small Generators

A file of readings has one number per line, with blank lines and # comments mixed in. You will read it with two small generators chained together. Each line goes through both of them before the next line is read, and nothing is read until someone asks for a number.

stream = pipeline(["1", "# note", "", "2"])  # reads nothing yet
next(stream)  # reads "1", returns 1
next(stream)  # reads "# note", "" and "2", returns 2

What to write

  • clean(lines) is a generator. For each line, strip the whitespace around it with line.strip(). Skip the line if it is then empty or starts with #. Otherwise yield the stripped line.
  • parse(lines) is a generator. It yields int(line) for each line it receives. If int() raises ValueError, let the error go to the caller. Do not skip the line.
  • pipeline(lines) chains the two: parse(clean(lines)).

Use yield in clean and parse, and do not build a list in any of the three. A stage then reads its next input line only when someone asks it for its next value.

Edge cases:

  • Empty input gives no numbers.
  • A line such as " # note" is a comment, because it starts with # once stripped. A line of only spaces is blank.
  • "-3" and "+4" are valid numbers, because int() accepts a sign.

What the driver reports

The starter comes with solve(lines, take). Do not change it. It hands the lines to your pipeline one at a time and logs read '<line>' each time it hands one out. It calls pipeline, logs created, then takes up to take numbers with islice and logs got <number> for each. It returns:

  • numbers: the numbers it took.
  • log: every event, in order.
  • error: the message of a ValueError from your pipeline, or "".

With a lazy pipeline, created comes first, and each got comes right after the reads that produced it. For lines=["10", "20", "oops"] and take=2, the driver stops after two numbers, so "oops" is never read and error is "". A version that builds lists reads every line before created, and fails on "oops" although nobody asked for it.