Convert, Compute, and Report

Keep the source line visible while converting valid readings, recording one expected failure, and computing a report from accepted values.

Reading measurements.txt gives the program one string for each source line. Numerical work needs a different representation: labels paired with floating-point readings. The conversion should happen near the input boundary, before those values reach the summary function.

Here is the same file, with its source line numbers shown for reference:

1  north,18.5
2  east,not recorded
3  west,24.0
4  café,21.5
5  north,19.0
6  west,23.5

Line 2 has invalid numeric text. Chapter 7 established the policy for this expected case: record which row was skipped and continue with the valid rows.

Parse the Stated Row Format

The file format says that each line has two comma-separated fields. We can therefore clean the line ending and split once at that stated separator:

For source line 4, the values are visible:

StageValue
source line"café,21.5\n"
cleaned line"café,21.5"
label"café"
reading text"21.5"

strip and split were introduced with strings in Chapter 5. Their use here comes from the file format: newline and surrounding whitespace are not fields, while the comma separates the two fields. If the format did not promise comma-separated fields, calling split(",") would be a guess rather than a parser.

Keep the source line number beside the row. A report such as “line 2 was skipped” is useful even when two rows share the same label or the invalid text is empty.

Q1. Preserve the source identity

After cleaning source line 4, which values should the parser keep before numeric conversion?

Choose one

Select one choice, then check.

HintRetain evidence before conversion

One value locates the row; the other two values come from splitting its stated fields.

SolutionKeep line number, label, and reading text

Retain 4, "café", and "21.5". The parser can then convert the reading while preserving where it came from.

Not attempted
Review

Not marked done.

Convert at the Input Boundary

The field named reading_text still contains a string. Convert it before adding the row to numerical data:

The try block contains only the expected conversion. A ValueError records the source line, label, and rejected text, then continue prevents that row from reaching accepted. Other defects remain visible rather than being mistaken for invalid input.

Tracing all six rows gives:

LineLabelReading textDecision
1north"18.5"accept 18.5
2east"not recorded"reject and record line 2
3west"24.0"accept 24.0
4café"21.5"accept 21.5
5north"19.0"accept 19.0
6west"23.5"accept 23.5

The accepted values are now suitable for computation. The rejected row remains evidence; it has not disappeared silently.

Q2. Choose the narrow invalid-row policy

What should happen when float("not recorded") raises ValueError for line 2?

Choose one

Select one choice, then check.

HintDo not invent or erase data

The source contains no numerical value for east, but its failed row still belongs in the report.

SolutionRecord and skip the invalid row

Add (2, "east", "not recorded") to the rejected rows and continue. The remaining numerical rows can still be summarized.

Not attempted
Review

Not marked done.

Keep Reading, Parsing, and Computation Separate

One function can own each role. The reader obtains source lines, and the parser converts those lines into clean records. This call supplies only accepted numbers to the already tested mean function; the function still preserves its earlier contract by ignoring an explicit None marker:

The boundaries are now visible:

FunctionReceivesReturns
read_linesa file pathnumbered text lines
parse_measurementsnumbered text linesaccepted numeric records and rejected-row evidence
meannumbers, with optional None markersthe mean of available numbers, or None when none are available

This separation keeps file details out of mean. It also lets a parsing test supply a short list of strings without opening a file, and lets a mean test supply numbers without constructing text rows.

Build Report Text from the Result

The accepted readings are 18.5, 24.0, 21.5, 19.0, and 23.5. Their computation is small enough to check by hand:

total = 18.5 + 24.0 + 21.5 + 19.0 + 23.5 = 106.5
count = 5
mean  = 106.5 / 5 = 21.3

The program can construct a short report from that result. Here, accepted, rejected, and values are the lists produced by the earlier functions:

join appears here because the program is constructing output text from separate report lines. The report has not yet been saved. The next lesson will write derived output and read it back before treating the write as verified.

Q3. Parse and summarize the measurement file

Replace the marked parser statements. Convert each reading near the input boundary, retain the invalid row, and leave the tested mean function unchanged. The program should report five accepted rows, one rejected row, and the checked mean.

Editable Python

Command/Ctrl + Enter. Python runs in your browser.

Ready to run.

HintKeep the successful append outside the handler

Replace 0.0 with float(reading_text). On ValueError, append a tuple containing line_number, label, and reading_text to rejected, then continue to the next source line.

SolutionConvert, record, and continue

Only a successful conversion reaches accepted.append. The values passed to mean are therefore all floating-point numbers.

Not attempted
Review

Not marked done.

Reading preserves numbered source text; parsing applies the stated field format and converts near the boundary; computation receives only clean numerical values. The invalid east row remains explicit rather than becoming zero or disappearing. The resulting report text is ready to be written and verified.

Pause and reflect

In your own words, note what you understood, what remains unclear, or what you want to revisit. The note stays with this lesson.

0 of 3 exercises marked done

Review

Not marked done.