learn
Weeks 7–9 · About 30 hours

Reading crashes, working with files, and finding bugs

How to read an error message instead of panicking, how to save and load data, and how to work out why a program is doing the wrong thing.

This is the difference between someone who can write code and someone who can fix code. Once you are into , most of your time will be spent working out why your returns the wrong answer. Being able to investigate calmly is what makes that survivable rather than demoralising. It is the least glamorous stage here and probably the highest-value one.

Reading a stack trace

When a program crashes, Python prints a report saying exactly which line failed and what went wrong. It looks intimidating and is actually a straight answer to your question.

Read it from the bottom up. The last line names the kind of problem and describes it — for example NameError: name 'totl' is not defined, which means you misspelt a variable. That bottom line is usually all you need.

Above it is the traceback: the chain of function calls that led to the failure, oldest at the top, most recent at the bottom. When your own code called a library that failed, this chain shows which of your lines started it.

A few you will meet constantly. NameError: you used a name that does not exist, usually a typo. TypeError: you did something to the wrong kind of value, like adding a number to text. IndexError: you asked for position 10 of a list holding 3 items. KeyError: you asked a dictionary for a label it does not have. ValueError: the kind was right but the value was not, like int("hello").

The skill to build here is simply not flinching. The error message is the most helpful thing in the room; beginners skip past it and start guessing, which turns a thirty-second fix into an hour.

Where you meet it in real softwareEvery language has this. Learning to read Python's makes reading any other one easier.

Handling exceptions

try and except let you say: attempt this, and if it goes wrong, do that instead of crashing.

The shape is try: followed by the risky steps, then except SomeError: followed by what to do about it. If nothing goes wrong, the except block is skipped entirely.

Catch the specific error you expect, not everything. A bare except: swallows every problem including the ones you have not thought of, which turns a loud crash into silent wrong behaviour. That is strictly worse — a crash tells you something is broken, silence does not.

The harder judgement is when not to catch at all. If your program genuinely cannot continue sensibly, letting it stop is the right answer. Catching an error and carrying on with nonsense data causes bugs that surface much later and much further away, which are the expensive kind.

Where you meet it in real softwareReading a file that might not exist, calling a service that might be down, parsing input a user might have typed wrong.

Reading and writing files

How to make your program save something that survives after it closes, and read it back next time.

Everything held in a variable disappears when the program ends. A file is how you keep it. You open a file, read from it or write to it, and close it.

The safe pattern is with open("notes.txt") as f: — the with part guarantees the file is properly closed even if something goes wrong in the middle. Get into the habit of always using it.

CSV files are just text where each line is a row and commas separate the columns — the format spreadsheets export. Python's built-in csv module handles the fiddly cases for you, such as a value that itself contains a comma. Do not try to split on commas by hand; that works right up until it suddenly does not.

Where you meet it in real softwareSaving user data, reading exported reports, log files, configuration.

Debugging

Working out why a program does the wrong thing, when it has not crashed and given you a clue.

Start with printing. Put print statements at the points where you have an assumption — print the value going into a function and the value coming out. Most bugs turn out to be a value that was not what you assumed, and this finds them.

Then graduate to the debugger, which is much better. You click beside a line number to set a breakpoint, run the program, and it pauses there. You can then look at every variable, and step forward one line at a time watching what changes. In VS Code this is the Run and Debug panel.

The reason it beats printing is that you do not have to guess in advance what to look at. You pause and inspect everything, including the things you did not suspect.

The underlying method matters more than the tool: form one specific guess about what is wrong, work out what you would see if that guess were true, then check. Changing things at random until the symptom disappears usually hides the bug rather than removing it.

Where you meet it in real softwareEvery working programmer does this daily. It is arguably the core professional skill.

Modules — splitting code across files

import lets one file use functions defined in another, so a program can be several tidy files instead of one enormous one.

Any .py file is a module. If you have helpers.py containing a function called clean(), then in another file you write import helpers and call helpers.clean(), or from helpers import clean to use the name directly.

Python also ships with a large — code that comes with the language, already tested, that you can import without installing anything. csv, math, random, json and collections are ones you will use constantly.

The habit worth forming: before writing something fiddly, check whether the standard library already has it. It usually does, and the version that ships with Python has been used by millions of people and has had its edge cases found already.

Where you meet it in real softwareEvery non-trivial program is organised into modules. It is how code stays navigable as it grows.

Reading about this stage is not the same as finishing it. Type every one of these from a blank file rather than copying — the writing is the part that teaches.

Text file statistics

Read a text file and report how many lines, words and characters it contains. Handle the file not existing, rather than crashing.

To-do list that survives restarting

Add tasks, mark them done, list them — and save to a file so everything is still there next time you run it. Your first program with persistence, which is a genuine step up.

CSV column averages

Read a CSV file and compute the average of a numeric column. Use the csv module. Deal with rows where the value is missing or is not a number, instead of letting it crash.

Break something on purpose, then fix it

Take one of your earlier programs and deliberately introduce three bugs: a typo in a variable name, an off-by-one error in a loop, and a wrong comparison. Then find each one using the debugger and a breakpoint, rather than by remembering what you changed. This is practice at the actual skill.

Exit checkGiven a program that crashes, you can find and fix the bug using the traceback and a breakpoint, without asking anyone for help.

If you cannot do this, repeat the stage rather than moving on. Nothing later gets easier by skipping it.

This stage corresponds to Phase 0 — Errors, Files, and Debugging in the source roadmap.