EE1021 Lecture 6 Worksheet — Debugging and Error Handling
Instructions
- Predict or state expected behavior before running code.
- Use the supplied function names in the submission template.
- Read tracebacks from the final line upward.
- Do not use bare
except,except Exception, or silentpasshandlers. - Keep
tryblocks focused on the operation you intend to handle. - Complete the eight core tasks before the optional extension.
1. Classify the Bug
Classify each problem as syntax error, runtime exception, or logic error. For runtime cases, name the likely exception.
print(values[4])whenvaluescontains two elements.if voltage > 5.0 print("high").- A program reports an average of 30 for
[10, 20, 30]. int("4.5").registry["S9"]when S9 is absent.- A Celsius conversion uses
c * 9 / 5 - 32.
2. Annotate a Traceback
Traceback (most recent call last):
File "monitor.py", line 11, in <module>
print(parse_reading(("T2", "error")))
File "monitor.py", line 6, in parse_reading
value = float(value_text)
ValueError: could not convert string to float: 'error'
Identify:
- exception type;
- exception message;
- innermost failing line;
- function containing the failure;
- input that reproduces it;
- one reasonable hypothesis.
3. Predict Exception Control Flow
Predict every printed line before running:
print("start")
try:
value = int("4.5")
print("converted")
except ValueError:
print("invalid integer")
print("end")Explain why one print statement is skipped.
4. Parse One Sensor Reading
Implement:
def parse_reading(record):
"""Return (sensor_id, value) for a (sensor_id, value_text) tuple."""Contract:
("T1", "23.5")returns("T1", 23.5);- a record that does not contain exactly two items raises
ValueError("expected (SENSOR, VALUE)"); - a nonnumeric value raises
ValueError("value must be numeric"); - the conversion
tryblock must contain only the conversion operation.
5. Required and Optional Sensor IDs
Implement:
def classify_reading(sensor, value, limits):
"""Return normal, alarm, or unknown."""An unknown sensor must return "unknown". A known sensor is "alarm" only when its value is strictly greater than its limit.
Explain why using an extremely large default limit could incorrectly label unknown sensors as normal.
6. Enforce the Average Contract
Implement:
def average_reading(values):
"""Return the average of a non-empty sequence."""Raise ValueError("values must not be empty") for empty input. Do not catch ZeroDivisionError. Verify:
[20.0]returns20.0;[20.0, 22.0, 24.0]returns22.0;[]raises the documented exception.
7. Narrow an Overly Broad Handler
record is a tuple such as ("T2", "error"). Rewrite this code so conversion and lookup failures receive different responses and unrelated defects remain visible:
try:
sensor, value_text = record
value = float(value_text)
limit = limits[sensor]
print(sensor, value, limit)
except Exception:
print("bad input")Use specific exception types and explain the boundary of each try block.
8. Engineering Mini-Problem: Process Records
Implement:
def process_records(records, limits):
"""Return (accepted, errors) after processing all records."""For every valid record, append (sensor, value, status) to accepted. For malformed structure or a nonnumeric value, append the exception message to errors and continue. Unknown sensors are valid parsed records with status "unknown".
Test with:
records = [("T1", "23.5"), ("T2", "error"), ("T5",), ("T9", "21.0")]
limits = {"T1": 80.0, "T2": 75.0}The result should contain two accepted records and two error messages.
Optional Extension (after L10, Files): Load a Text File
Load one record per line from sensor_readings.txt, strip newline characters, and pass the list to process_records. Catch file-system exceptions only at the user-interface boundary, where you can report a filename and decide whether recovery is possible.
Submission Checklist
- All eight core tasks are complete.
- Every bug is classified before repair.
- Traceback evidence is annotated.
- No bare or broad exception handler remains.
- Conversion is handled in a narrow
tryblock. - Unknown sensors are not silently treated as normal.
- Empty input raises the documented
ValueError. - Normal, boundary, and invalid cases are tested.