Lesson 20 · 20 of 20
Project: grade report · Python
A project that brings the basic Python course together: it reads marks from a file, skips bad data and prints a report with averages and grades.

This program puts together almost everything in the course. It starts with a function, grade(), that turns an average into a letter with if and return: as soon as a condition is true, it returns the letter and stops.
Then it writes a file, marks.txt, with one line per student and opens it again for reading, line by line. line.split(":") separates the name from the marks and is unpacked into name and text.
The marks are split with split(",") and each one is converted with float(), which accepts the surrounding spaces. Ben has a «five» written in letters: float() raises a ValueError, the except reports it and that mark is dropped without stopping the program.
The valid marks are added to the list marks, and each student's average is stored in the dictionary averages, with the name as the key.
Finally, a for loop over averages.items() prints the report in columns with f-strings, notes who passed in the passed list and remembers the best average. ", ".join(passed) puts the names on a single line.
Code · main.py
# Grade report: files, strings, lists, dicts, functions and errors.def grade(mark): if mark >= 9: return "A" if mark >= 7: return "B" if mark >= 5: return "C" return "F"with open("marks.txt", "w") as file: file.write("Ana: 8, 9.5, 7\nBen: 4, 6, five\nCarla: 9, 10, 9.5\nDani: 3, 5, 4\n")averages = {}with open("marks.txt") as file: for line in file: name, text = line.split(":") marks = [] for part in text.split(","): try: marks.append(float(part)) except ValueError: print(f"{name}: '{part.strip()}' is not a mark, skipped") averages[name] = sum(marks) / len(marks)print(f"{'Student':<8}{'Avg':>6} Grade")passed, best_name, best = [], "", 0for name, avg in averages.items(): print(f"{name:<8}{avg:>6.2f} {grade(avg)}") if avg >= 5: passed.append(name) if avg > best: best_name, best = name, avgprint("Passed:", ", ".join(passed))print(f"Best average: {best_name} ({best:.2f})")Output · python3 main.py
Ben: 'five' is not a mark, skipped Student Avg Grade Ana 8.17 B Ben 5.00 C Carla 9.50 A Dani 4.00 F Passed: Ana, Ben, Carla Best average: Carla (9.50)
Key points
- Functions split the program into named pieces.
- Files plus
split()turn text into data. try/exceptstops one bad value from stopping the program.- Lists and dictionaries hold the results for the report.
- F-strings with widths line up the table.
Exercise
Extend the project so it saves the report to a report.txt file and adds the class average and how many students got each letter (with a dictionary of counters).