Parser function
The feed parser from "Line to record" lives inside one loop in one program. The alert checker and the daily report want to parse telemetry lines too, and copying the loop into each of them is how bugs get fixed in one place and not the other.
Turn the parsing into a function that any program can call, then let it decide on its own which lines are worth a record.
Finish stage 1 to unlock this stage.
Move the parsing of one line into a function parse_line(line) that returns the record dict, and call it in the loop. The output must stay exactly the same:
Records: 4
{'time': '09:30:05', 'sensor': 'ENG-2', 'value': 412.5, 'unit': 'C'}
{'time': '09:30:05', 'sensor': 'TANK-1', 'value': 78.3, 'unit': '%'}
{'time': '09:30:10', 'sensor': 'CABIN', 'value': 101.2, 'unit': 'kPa'}
{'time': '09:30:10', 'sensor': 'ENG-2', 'value': 415.0, 'unit': 'C'}The function takes one line, splits it, and returns the dict. The loop still skips blank and comment lines, then appends parse_line(line).
Finish stage 1 to unlock this stage.
Move the skipping into the function as well. parse_line() strips the line, so spaces around a good line don't end up in its fields, and returns None for a blank line, a comment, or a line that doesn't have exactly four fields. The loop just keeps whatever isn't None. The output stays the same:
Records: 4
{'time': '09:30:05', 'sensor': 'ENG-2', 'value': 412.5, 'unit': 'C'}
{'time': '09:30:05', 'sensor': 'TANK-1', 'value': 78.3, 'unit': '%'}
{'time': '09:30:10', 'sensor': 'CABIN', 'value': 101.2, 'unit': 'kPa'}
{'time': '09:30:10', 'sensor': 'ENG-2', 'value': 415.0, 'unit': 'C'}In the loop: record = parse_line(line), then append it if record is not None.
Hints
Returning Dictionary or List
# Returning complex data structures from functions
def planet_data(name):
"""Returns dictionary with planet info."""
database = {
"Mars": {"diameter_km": 6779, "moons": 2, "type": "rocky"},
"Jupiter": {"diameter_km": 139820, "moons": 95, "type": "gas giant"},
"Saturn": {"diameter_km": 116460, "moons": 146, "type": "gas giant"}
}
return database.get(name, {"error": f"Planet {name} not found"})
def mission_checklist(crew_size, days):
"""Returns list of supply items scaled to crew and duration."""
water_liters = crew_size * days * 2.5
food_kg = crew_size * days * 1.8
oxygen_kg = crew_size * days * 0.84
return [
f"Water: {water_liters:.0f} liters",
f"Food: {food_kg:.0f} kg",
f"Oxygen: {oxygen_kg:.1f} kg"
]
mars = planet_data("Mars")
print(f"Mars has {mars['moons']} moons and is {mars['type']}")
pluto = planet_data("Pluto")
print(pluto)
supplies = mission_checklist(4, 180)
print("Mission supplies needed:")
for item in supplies:
print(f" - {item}")
Separate arguments with commas. They're passed on every Run as sys.argv[1:].