Execution and Errors: Running and Debugging Code

Before You Start

You should know: - How to launch Jupyter Notebooks from the command line.

You will learn: - The three distinct ways your computer can execute Python code (Interactive, Scripts, and Notebooks). - How to deliberately break your code. - Why Error Messages (Tracebacks) are not punishments, but precise roadmaps.

Introduction

At this stage, you have an activated sandbox equipped with mathematical packages, and you know how to launch an interactive Jupyter Notebook. There is only one final barrier before writing actual geographic models: figuring out what happens when your code inevitably breaks.

You will spend substantially more time debugging code than you will writing it. This is normal. Professional software engineers spend up to 70% of their day deciphering errors!

To become an effective debugger, you have to understand the three ways Python runs, and how to read the β€œTracebacks” Python generates when it gets confused.

The Three Faces of Python

There are three ways to execute code, and you will routinely switch between them depending on the puzzle you are trying to solve.

1. The Interactive Shell (The Calculator)

If you simply open your terminal and type python (and press Enter), you enter Python’s interactive shell. Your terminal prompt will change to >>>. You are now communicating with the Python brain in real-time. If you type 10 * 5 and hit enter, it immediately replies 50. When to use it: When you want to check a single syntax, try out a simple equation, or aggressively test a one-line command without saving a file. Type exit() to leave.

2. The Jupyter Notebook (The Sandbox)

As we saw in the last chapter, Jupyter stores blocks of code and executes them piecemeal in an interactive web browser. When to use it: When you are exploring a novel dataset, generating maps, or iteratively testing a complex formula. The notebook remembers the variables you ran in earlier cells, giving you enormous freedom to dynamically manipulate data.

3. The Script (The Final Product)

A script is a plain text file ending in .py, filled with Python code. It is executed linearly from top to bottom. To run it, you go to your terminal and type python my_script.py. When to use it: Once you have figured out your logic perfectly inside a Jupyter Notebook, you copy the cleaned code into a .py script. Scripts are used for automation, deploying models, and handling massive data pipelines that don’t need a human to click a button for every step.

The Art of Breaking Code

Let’s deliberately break Python. In either a Jupyter Notebook or a .py script, try running this impossible math operation:

gravity = 9.81
mass = "ten kilograms"
force = gravity * mass
print(force)

Python will crash aggressively and print red text. This block of screaming text is called a Traceback.

Reading a Traceback

When beginners see an error message, they panic, assume they broke their computer, and immediately begin randomly changing code to make the red text vanish.

A traceback is actually a highly specific, very polite note from Python telling you exactly what it was doing at the moment it gave up.

A traceback must be read from the bottom up.

Step 1: The Error Type (The Bottom Line)

Always look at the very last line of the traceback. In our example, it will say: TypeError: can't multiply sequence by non-int of type 'float'

The bottom line tells you what Python is confused about. In this case, a TypeError means you handed it data of the wrong structure. You told it to multiply a decimal number (9.81) by English text ("ten kilograms"). Python doesn’t know how to do numerical math on words, so it surrendered.

Step 2: The Location (One Line Up)

Look slightly above the Error Type. The traceback will highlight the specific line of code that triggered the meltdown: ----> 3 force = gravity * mass

This tells you exactly where to start fixing the problem.

Common Errors to Memorize

  • SyntaxError: You made a typo. You forgot a parenthesis, missed a colon, or spelled a core Python command wrong.
  • NameError: You tried to use a variable that doesn’t exist yet! You probably mistyped a variable name (like gravty instead of gravity).
  • FileNotFoundError: Python looked in your current working directory (remember pwd?) and could not find the file you told it to open.
  • ModuleNotFoundError: You forgot to pip install or conda install the package before attempting to use it.

The Debugging Mindset

Once you learn to read tracebacks, you need one more habit: isolate the problem.

When code breaks, beginners try to fix it by changing multiple things at once. This makes things worse. Instead:

  1. Read the traceback. Identify the exact line and error type.
  2. Form a hypothesis. β€œI think the problem is that mass is a string, not a number.”
  3. Change one thing. Fix only the suspected cause.
  4. Run again. If it fails, you rule out that hypothesis and try the next one.

This sounds obvious written down. In practice, it is the hardest habit to build because panicked brains want to change everything at once.

A useful trick: add a print() statement just before the line that crashes to confirm your variables hold the values you expect.

gravity = 9.81
mass = "ten kilograms"
print("gravity:", gravity, "| mass:", mass, "| type:", type(mass))  # diagnostic
force = gravity * mass  # crashes here

When you run this, you’ll see exactly what Python was holding in memory at the moment it gave up. Most of the time, the bug is immediately obvious.

Running Scripts from the Command Line

When your analysis is finished and debugged in a notebook, the final step is turning it into a reusable script.

Save your logic as a .py file and run it from your terminal:

python my_analysis.py

A few things to know:

Your working directory matters. If your script opens a data file with open("temperatures.csv"), Python looks for that file in the folder where your terminal is currently standing (pwd). If the file is somewhere else, you will get a FileNotFoundError. Always cd into your project folder before running scripts, or use absolute paths.

Standard output is your friend. In a notebook, each cell displays its result automatically. In a script, nothing is displayed unless you explicitly call print(). Add progress messages so you know the script is running:

print("Loading data...")
data = load_big_dataset()

print("Processing 1,000 rows...")
results = process(data)

print("Done. Results saved to output.csv")

Exit codes. When a script finishes cleanly, your terminal gets control back. If it crashes, the traceback is printed to the terminal exactly as you’d see it in a notebook. There is no difference in how Python reports errors β€” the same traceback, the same bottom-up reading rule.

Verify Your Work

  1. Open your terminal and type python. Try running some basic math in the interactive shell (2 ** 8, len("hello")), then type exit() to leave.
  2. Launch a Jupyter Notebook. Write the broken gravity code from this chapter and run the cell. Read the traceback from the bottom up before touching anything.
  3. Add a print() diagnostic line before the crash. Confirm it shows the type mismatch.
  4. Fix the code by changing "ten kilograms" to 10. Run the cell. Confirm the error is gone and the output is correct.
  5. Copy the working code to a .py file. Open a terminal, cd to the folder containing it, and run python your_file.py. Confirm the output appears in the terminal.

When you can move fluidly between the shell, a notebook, and a script β€” and when a red traceback no longer triggers panic β€” you are ready for the professional workflow tools in the next chapter.