Python, Concept by Concept › Files
Exercises: Files
Core work is Exercises 1–10. Exercises 11–24 are More Practice; Exercises 25–28 are optional Challenges. Every file exercise supplies its own known data before reading, so you can run it again safely. The real programs read values with input(), save them, reload them, and print the answer.
Keep each exact function name and parameter list. Use a with open(...) block for every file operation, with the explicit mode "w", "r", or "a". Define each function, then try all its worked sample calls. The starter cells contain comments only.
Exercise 1: Save and Read a Labeled Score Report
An arcade manager wants a score report whose first line clearly labels the numbers below it.
Specification: Define score_text_with_header(scores, path). First open path in "w" mode with a with statement. Write the fixed header line ARCADE SCORES with f.write(f"ARCADE SCORES\n"), then loop through scores and write one score per f-string line. After that file closes, open the same path with with open(path, "r") as f: and use f.read() to load the whole file. Return all the loaded text, including the header. Use ex1_scores.txt.
Worked sample calls:
score_text_with_header([45, 70, 55], "ex1_scores.txt") -> "ARCADE SCORES\n45\n70\n55\n"
score_text_with_header([120, 95], "ex1_scores.txt") -> "ARCADE SCORES\n120\n95\n"
score_text_with_header([300], "ex1_scores.txt") -> "ARCADE SCORES\n300\n"
Real program
The real program reads a count and that many scores with input(), saves the report, reloads it, and prints its text.
How this is checked: Checked by tests that run your function score_text_with_header.
Exercise 2: Rebuild the Number List
A puzzle judge needs the saved score lines back as integers, not text.
Specification: Define score_list_round_trip(scores, path). First write every score to path, one per line, in "w" mode. Then make a new empty list, open the same path with with open(path, "r") as f:, and use for line in f:. Transform each line with int(line.strip()) and append the integer. Return the rebuilt list. Use ex2_score_list.txt.
Worked sample calls:
score_list_round_trip([18, 27, 36], "ex2_score_list.txt") -> [18, 27, 36]
score_list_round_trip([5, 105], "ex2_score_list.txt") -> [5, 105]
score_list_round_trip([42], "ex2_score_list.txt") -> [42]
Real program
The real program reads one line of scores with input(), saves them, reloads them as integers, and prints the list.
How this is checked: Checked by tests that run your function score_list_round_trip.
Exercise 3: Total and Count the Saved Tickets
A prize booth needs both the total number of saved tickets and the number of awards that reached a goal.
Specification: Define saved_ticket_report(tickets, target, path). First write every ticket number to path, one per line. Start total = 0 and count = 0, then open the same path with with open(path, "r") as f:. Use one for line in f: loop. Convert each line with int(line.strip()), add that number to total, and add 1 to count when the number is at least target. Return [total, count]. Do not build a loaded list and do not call sum. Use ex3_tickets.txt.
Worked sample calls:
saved_ticket_report([20, 35, 15], 25, "ex3_tickets.txt") -> [70, 1]
saved_ticket_report([100, 50], 50, "ex3_tickets.txt") -> [150, 2]
saved_ticket_report([9, 12, 7], 20, "ex3_tickets.txt") -> [28, 0]
Real program
The real program reads a target, a count, and that many ticket values with input(), saves them, reloads them, and prints the report.
How this is checked: Checked by tests that run your function saved_ticket_report.
Exercise 4: Build a Four-Number Summary
A tournament screen needs the lowest score, highest score, total, and number of scores from one saved round.
Specification: Define saved_score_summary(scores, path). First write every score to path, one per line. Then build a new integer list by opening the same path with with open(path, "r") as f:, looping through its lines, changing each line with int(line.strip()), and appending it. Return [min(loaded), max(loaded), sum(loaded), len(loaded)]. The supplied list always has at least one score. Use ex4_summary.txt.
Worked sample calls:
saved_score_summary([8, 15, 11], "ex4_summary.txt") -> [8, 15, 34, 3]
saved_score_summary([50, 20], "ex4_summary.txt") -> [20, 50, 70, 2]
saved_score_summary([99], "ex4_summary.txt") -> [99, 99, 99, 1]
Real program
The real program reads a count and that many scores with input(), saves them, reloads them, and prints the summary.
How this is checked: Checked by tests that run your function saved_score_summary.
Exercise 5: Find the Saved High Score by Scanning
A scorekeeper wants to see the best result found so far while scanning a saved file.
Specification: Define highest_saved_score(scores, path). The supplied list always has at least one score. First write every score to path, one per line. Set best = scores[0], then open the same path with with open(path, "r") as f: and use for line in f:. Convert the cleaned line with int(line.strip()). If that score is greater than best, replace best. Return best. Do not call max. Use ex5_high_score.txt.
Worked sample calls:
highest_saved_score([44, 81, 63], "ex5_high_score.txt") -> 81
highest_saved_score([205, 199, 201], "ex5_high_score.txt") -> 205
highest_saved_score([17], "ex5_high_score.txt") -> 17
Real program
The real program reads a count and that many scores with input(), saves them, reloads them, and prints the highest score.
How this is checked: Checked by tests that run your function highest_saved_score.
Exercise 6: Build a Saved Player Summary
A league report needs one readable summary built from a saved name, level, and points.
Specification: Define player_record_summary(name, level, points, path). First write name, level, and points to path on three separate lines, using an f-string for each write. Then open the same path with with open(path, "r") as f:. Read the three saved lines in order with f.readline(). Strip the saved name and convert the saved level and points with int(...). Return an f-string in the exact form "name: level level, points points". Use ex6_typed_record.txt.
Worked sample calls:
player_record_summary("Lina", 3, 480, "ex6_typed_record.txt") -> "Lina: level 3, 480 points"
player_record_summary("Mateo", 5, 925, "ex6_typed_record.txt") -> "Mateo: level 5, 925 points"
player_record_summary("Zoe", 1, 75, "ex6_typed_record.txt") -> "Zoe: level 1, 75 points"
Real program
The real program reads a name, level, and points with input(), saves the record, reloads it, and prints the summary.
How this is checked: Checked by tests that run your function player_record_summary.
Exercise 7: Search a Saved Roster
A check-in desk saves a roster with one player name per line, then checks the saved lines in order for an exact match.
Specification: Define save_and_find_player(names, target, path). First write every name to path, one per line, with f.write(f"{name}\n"). Then open the same path with with open(path, "r") as f:. Use exactly for line in f:, followed by if line.strip() == target: and an immediate return of f"Found {target}.". After the loop, return f"{target} was not found.". Do not load the whole file or use a text-membership search. Use ex7_roster.txt.
Worked sample calls:
save_and_find_player(["Inez", "Kai", "Noor"], "Inez", "ex7_roster.txt") -> "Found Inez."
save_and_find_player(["Inez", "Kai", "Noor"], "Noor", "ex7_roster.txt") -> "Found Noor."
save_and_find_player(["Inez", "Kai", "Noor"], "Pia", "ex7_roster.txt") -> "Pia was not found."
Real program
The real program reads a target name, a count, and that many names with input(), saves the roster, reloads it, and prints the search result.
How this is checked: Checked by tests that run your function save_and_find_player.
Exercise 8: Append a Late Score
A late round arrives after the first scores have already been saved.
Specification: Define append_round_trip(scores, late_score, path). Write the original scores one per line with "w". Append the late score with a separate "a" block. Reload every line as an integer and return the list. Put a short purpose comment above the function. Use ex8_late_score.txt.
Worked sample calls:
append_round_trip([62, 48], 91, "ex8_late_score.txt") -> [62, 48, 91]
Real program
The real program reads a count, that many scores, and a late score with input(), saves and appends them, reloads the file, and prints the list.
How this is checked: Checked by tests that run your function append_round_trip.
Exercise 9: Save a Text Map
A tiny map must survive after the drawing program stops.
Specification: Define map_round_trip(rows, path). Write one row per line with "w", then reload each row with strip() and append it to a new list. Return the saved rows with no extra newlines. Put a short purpose comment above the function. Use ex9_map.txt.
Worked sample calls:
map_round_trip(["#.#", "...", "#.#"], "ex9_map.txt") -> ['#.#', '...', '#.#']
Real program
The real program reads a count and that many map rows with input(), saves them, reloads them, and prints the list.
How this is checked: Checked by tests that run your function map_round_trip.
Exercise 10: Best Team from Records
A score table stores each team and its points together on one comma-separated line.
Specification: Define best_team(records, path) for at least one record in "name,points" form. Every points value is 0 or more. Save the lines with "w", then reload them. For each line, use parts = line.strip().split(",") and int(parts[1]). Seed best_points = -1 and best_name = "". Update both only for strictly greater points; ties keep the first team. Return its name. Put a short purpose comment above the function. Use ex10_teams.txt.
Worked sample calls:
best_team(["Ivo,15", "Uma,9", "Teo,22"], "ex10_teams.txt") -> "Teo"
Real program
The real program reads a count and that many comma-separated team records with input(), saves them, reloads them, and prints the best team.
How this is checked: Checked by tests that run your function best_team.
Exercise 11: More Practice: Long Words in a File
A text report counts words longer than three letters.
Specification: Define long_word_count(lines, path). Save each line, then loop through the saved file. For each line.split(), count words whose length is greater than 3. Return the count. Use ex11_words.txt.
Worked sample calls:
long_word_count(["red sails drift", "past docks"], "ex11_words.txt") -> 4
Real program
The real program reads a count and that many text lines with input(), saves them, reloads them, and prints the count.
How this is checked: Checked by tests that run your function long_word_count.
Exercise 12: More Practice: Longest Saved Line
A sign maker wants the longest complete line from a saved list.
Specification: Define longest_line(lines, path) for a nonempty list. Save each line, then reload and strip each line. Track the best text and update it only with strict > length, so a tie keeps the first longest line. Return that text. Use ex12_longest.txt.
Worked sample calls:
longest_line(["ash", "fir hollow", "oak"], "ex12_longest.txt") -> "fir hollow"
Real program
The real program reads a count and that many text lines with input(), saves them, reloads them, and prints the longest line.
How this is checked: Checked by tests that run your function longest_line.
Exercise 13: More Practice: Numbered Lines
A recipe display adds line numbers after loading saved steps.
Specification: Define numbered(lines, path). Save each line, then reload the file. Start number = 1; for each stripped line append f"{number}: {text}" to a rows list and increase the number. Return "\n".join(rows) without a trailing newline. Use ex13_numbered.txt.
Worked sample calls:
numbered(["whisk batter", "add eggs", "bake"], "ex13_numbered.txt") -> "1: whisk batter\n2: add eggs\n3: bake"
Real program
The real program reads a count and that many steps with input(), saves them, reloads them, and prints the numbered lines.
How this is checked: Checked by tests that run your function numbered.
Exercise 14: More Practice: Average from a File
A score report needs an average calculated from saved numbers.
Specification: Define saved_average(scores, path) for a nonempty list. Save the scores, then reload each line as an integer. Keep a running total and count, and return total / count. In the stand-in and real program print f"Average: {average}". Use ex14_average.txt.
Worked sample calls:
saved_average([70, 80, 96], "ex14_average.txt") -> 82.0; printed: Average: 82.0
Real program
The real program reads a count and that many scores with input(), saves them, reloads them, and prints the labeled average.
How this is checked: Checked by tests that run your function saved_average.
Exercise 15: More Practice: Grade Report
A class report counts scores in four bands.
Specification: Define grade_report(scores, path). Save the scores and reload each as an integer. Start four counters at zero. While reading, use one if/elif/elif/else chain: A for at least 90, B for at least 80, C for at least 70, and D otherwise. Return four f-string rows joined with "\n", labeled A:, B:, C:, D:. Use ex15_grades.txt.
Worked sample calls:
grade_report([91, 78, 85, 62, 97], "ex15_grades.txt") -> "A: 2\nB: 1\nC: 1\nD: 1"
Real program
The real program reads a count and that many scores with input(), saves them, reloads them, and prints the labeled grade report.
How this is checked: Checked by tests that run your function grade_report.
Exercise 16: More Practice: Shout Copy
A second file holds an uppercase copy of saved announcements.
Specification: Define shout_copy(lines, source, target). Write the lines to source with "w". Read source line by line and write each .upper() line to target with "w". You may open the target file inside the source file's with block, or first read the lines into a list and then write them. Reload target, strip each line, and return the list. Use ex16_source.txt and ex16_target.txt.
Worked sample calls:
shout_copy(["hush now", "well done"], "ex16_source.txt", "ex16_target.txt") -> ['HUSH NOW', 'WELL DONE']
Real program
The real program reads a count and that many announcements with input(), saves them, reloads and copies them, then prints the copied lines.
How this is checked: Checked by tests that run your function shout_copy.
Exercise 17: More Practice: Keep the To-Dos
Only unfinished lines should reach a second file.
Specification: Define keep_todo(lines, source, target). Save lines to source. While reading it, write only lines whose stripped text startswith("TODO") to target. Reload target, strip its lines, and return the list. Use ex17_source.txt and ex17_target.txt.
Worked sample calls:
keep_todo(["TODO paint", "done sweep", "TODO wash"], "ex17_source.txt", "ex17_target.txt") -> ['TODO paint', 'TODO wash']
Real program
The real program reads a count and that many task lines with input(), saves them, reloads and filters them into a second file, then prints the kept tasks.
How this is checked: Checked by tests that run your function keep_todo.
Exercise 18: More Practice: Event Log
An event logger keeps a header and appends events as they arrive.
Specification: Define log_events(events, path). Write LOG and a newline with "w". For each event, use its own with open(path, "a") block to append the event and newline. Reload all lines with strip() and return the list. Use ex18_log.txt.
Worked sample calls:
log_events(["start", "jump", "land"], "ex18_log.txt") -> ['LOG', 'start', 'jump', 'land']
Real program
The real program reads a count and that many events with input(), saves and appends them, reloads the log, and prints the list.
How this is checked: Checked by tests that run your function log_events.
Exercise 19: More Practice: First Long Word
A search stops at the first saved word that reaches a minimum length.
Specification: Define first_long_word(words, minimum, path). Save one word per line. While reading, return the first stripped word with len(word) >= minimum. Return "none" only after the loop finishes. Use ex19_first.txt.
Worked sample calls:
first_long_word(["sky", "meadow", "brook"], 5, "ex19_first.txt") -> "meadow"
Real program
The real program reads a minimum, a count, and that many words with input(), saves them, reloads them, and prints the first match.
How this is checked: Checked by tests that run your function first_long_word.
Exercise 20: More Practice: Line of a Name
A roster search needs the line number of its first match.
Specification: Define line_of(names, target, path). Save one name per line. While reloading, start a line counter at 0 and increase it for each line. Return the line number immediately for the first exact match; return -1 after the loop if none matches. Use ex20_names.txt.
Worked sample calls:
line_of(["Rae", "Tovi", "Wen"], "Wen", "ex20_names.txt") -> 3
line_of(["Rae", "Tovi", "Wen"], "Zia", "ex20_names.txt") -> -1
Real program
The real program reads a target, a count, and that many names with input(), saves them, reloads them, and prints the matching line number.
How this is checked: Checked by tests that run your function line_of.
Exercise 21: More Practice: Chart from a File
A saved number list becomes a small text chart.
Specification: Define chart_from_file(values, path). Save one number per line. Reload each as an integer, append "#" * number to a rows list, and return "\n".join(rows) with no trailing spaces. Use ex21_chart.txt.
Worked sample calls:
chart_from_file([3, 1, 4], "ex21_chart.txt") -> "###\n#\n####"
Real program
The real program reads a count and that many bar lengths with input(), saves them, reloads them, and prints the chart.
How this is checked: Checked by tests that run your function chart_from_file.
Exercise 22: More Practice: Fix the Missing File
A reader opens a file that its program has never created.
Specification: Read the broken code and exact error below. Define read_saved_twelve(path) that first writes 12 and a newline to path with "w", then opens it with "r" and returns the stripped text. The repaired call prints 12. Use ex22_scores.txt for your function.
with open("missing_scores.txt", "r") as f:
print(f.read())
FileNotFoundError: [Errno 2] No such file or directory: 'missing_scores.txt'
Worked sample calls:
read_saved_twelve("ex22_scores.txt") -> "12"; printed: 12
How this is checked: Checked by tests that run your function read_saved_twelve.
Exercise 23: More Practice: Fix the Write Mode
A saved file exists, but the next operation opens it for reading before trying to write.
Specification: Read the broken code and exact error below. Define write_five(path) that writes 5 and a newline with "w", then reads it back with "r" and returns the stripped text. The repaired call prints 5. Use ex23_mode.txt.
with open("ex_mode.txt", "w") as f:
f.write("0\n")
with open("ex_mode.txt", "r") as f:
f.write("5\n")
io.UnsupportedOperation: not writable
Worked sample calls:
write_five("ex23_mode.txt") -> "5"; printed: 5
How this is checked: Checked by tests that run your function write_five.
Exercise 24: More Practice: Predict the Overwrite
Two fresh saves and an append are made to the same path.
Specification: Trace the code below before running it. Define predict_overwrite(path) that does the same three writes to its own path and returns the final stripped file text. Explain why the first 1 disappears and the file prints 2 then 3. Use ex24_overwrite.txt.
with open("ex24_overwrite.txt", "w") as f:
f.write("1\n")
with open("ex24_overwrite.txt", "w") as f:
f.write("2\n")
with open("ex24_overwrite.txt", "a") as f:
f.write("3\n")
with open("ex24_overwrite.txt", "r") as f:
print(f.read().strip())
This code runs without an error. Predict its two printed lines.
Worked sample calls:
predict_overwrite("ex24_overwrite.txt") -> "2\n3"; printed on two lines: 2 / 3
Starter (read-only)
# Define predict_overwrite(path), then try all sample calls.How this is checked: Checked by comparing your prediction with what the program really prints.
Answer format: several lines
Challenge
Exercises 25–28 combine file skills. They are optional stretch work.
Exercise 25: Prove That a Fresh Save Replaces the Old One
An arcade manager saves a corrected score list to the same path and wants proof that only the new scores remain.
Specification: Define replace_and_load_scores(first_scores, final_scores, path). First write every value from first_scores to path in "w" mode. After that file closes, open the same path in "w" mode again and write every value from final_scores. Then make an empty list, open the path with with open(path, "r") as f:, transform each line with int(line.strip()), and append it. Return the loaded list, which must contain only the final scores. Use ex25_replace.txt.
Worked sample calls:
replace_and_load_scores([10, 20], [30, 40], "ex25_replace.txt") -> [30, 40]
replace_and_load_scores([99], [4, 5, 6], "ex25_replace.txt") -> [4, 5, 6]
replace_and_load_scores([7, 8, 9], [100], "ex25_replace.txt") -> [100]
Real program
The real program reads both score lists with input(), saves them, reloads them, and prints the final list.
How this is checked: Checked by tests that run your function replace_and_load_scores.
Exercise 26: Find Two Statistics in One Pass
A tournament display needs a saved round's total and best score, calculated together while the file is read once.
Specification: Define saved_total_and_best(scores, path). The supplied list always has at least one score. First write every score to path, one per line. Start total = 0 and best = scores[0]. Open the same path with with open(path, "r") as f: and use one for line in f: loop. Convert each line with int(line.strip()), add the score to total, and replace best when the score is greater. Return [total, best]. Do not call sum or max. Use ex26_combined_stats.txt.
Worked sample calls:
saved_total_and_best([12, 30, 18], "ex26_combined_stats.txt") -> [60, 30]
saved_total_and_best([75, 20], "ex26_combined_stats.txt") -> [95, 75]
saved_total_and_best([9], "ex26_combined_stats.txt") -> [9, 9]
Real program
The real program reads a count and that many scores with input(), saves them, reloads them, and prints the total and best.
How this is checked: Checked by tests that run your function saved_total_and_best.
Exercise 27: Merge Two Score Files
Two teams save scores separately and need one ordered result.
Specification: Define merge_files(first, second, path_a, path_b). Save each list to its own file. Reload both files as integers, combine them, call .sort(), and return the ascending list. Use ex27_first.txt and ex27_second.txt.
Worked sample calls:
merge_files([12, 40], [25, 3], "ex27_first.txt", "ex27_second.txt") -> [3, 12, 25, 40]
Real program
The real program reads two counts and their score lines with input(), saves both files, reloads them, and prints the merged list.
How this is checked: Checked by tests that run your function merge_files.
Exercise 28: High-Score Table
A new score may change a saved top-three board.
Specification: Define update_high_scores(scores, new_score, path) for at least three starting scores. Save the original scores and reload them as integers. Add new_score, call sorted, and select indexes -1, -2, and -3 in that order. Rewrite path with only those top three scores, reload it, and return the reloaded list. Use ex28_high_scores.txt.
Worked sample calls:
update_high_scores([900, 850, 700], 880, "ex28_high_scores.txt") -> [900, 880, 850]
Real program
The real program reads a count, that many scores, and a new score with input(), saves them, reloads and updates the table, and prints the top three.
How this is checked: Checked by tests that run your function update_high_scores.