Skip to content
Course contents
The core of the language

When things go wrong

Real data is messy and code breaks, so you learn to anticipate failure with try and except, handling a missing value or a bad input gracefully rather than crashing. This is the habit that separates fragile scripts from dependable ones.

7 min readChapter 12 of 30
What you will learn
  • Read and understand common exceptions
  • Use try and except to handle a failure
  • Reason about what can go wrong with real market data

Back in your first program, an error stopped everything and showed a message. That is fine while you are learning, but a program that processes real market data cannot simply fall over the first time it meets a missing price or a blank cell, because real data is always messy. The professional habit is to anticipate failure and handle it, so the program deals with the bad row and carries on. Python's tool for that is try and except, and learning it is what turns a fragile script into a dependable one.

Catching a failure

try and except let code anticipate failure and handle a bad value gracefully instead of crashing, which is what makes a script dependable.
try and except let code anticipate failure and handle a bad value gracefully instead of crashing, which is what makes a script dependable.

When something goes wrong, Python raises an exception, a named error like the KeyError you met with dictionaries or a ZeroDivisionError from dividing by zero. A try block lets you attempt something that might fail, and an except block says what to do if a particular exception occurs, instead of crashing. This program handles both a missing symbol and a zero divisor.

ExampleHandling a missing key and a division by zeroch12/handling_errors.py
# Real data is messy, so anticipate failure with try / except.
prices = {"RELIANCE": 1402.5, "TCS": 3120.0}

def get_price(symbol):
    try:
        return prices[symbol]
    except KeyError:
        print(f"No price for {symbol}; skipping")
        return None

print(get_price("RELIANCE"))
print(get_price("WIPRO"))

def safe_return(buy, sell):
    try:
        return (sell - buy) / buy * 100
    except ZeroDivisionError:
        print("Buy price was zero; cannot compute return")
        return None

print(safe_return(1400, 1540))
print(safe_return(0, 1540))
Output
1402.5
No price for WIPRO; skipping
None
10.0
Buy price was zero; cannot compute return
None

The first function tries to look up a symbol's price. For "RELIANCE" it succeeds and returns 1402.5. For "WIPRO", which is not in the data, the lookup would normally raise a KeyError and stop the program; instead the except block catches it, prints a calm message, and returns None, so the program continues and simply reports None for the missing symbol. The second function guards a return calculation against a zero buy price: a normal call gives 10.0, but calling it with a buy price of zero, which would be a division by zero, is caught and handled rather than crashing. In both cases the program meets bad input and keeps going.

Thinking about what can go wrong

The deeper skill here is not the syntax but the mindset. Real market data, as the data chapters ahead will show, is full of gaps: a stock that was not trading that day, a symbol that was renamed, a blank where a price should be, a corporate action that makes a number look absurd. Code that assumes every value is present and sensible will break on the first exception, often deep inside a long run, losing all the work. Code that anticipates the likely failures, a missing key, a bad number, an empty series, handles them where they happen and produces a trustworthy result from imperfect data.

A word of balance. You do not wrap every line in a try block; that hides real bugs and makes code unreadable. You use it where failure is genuinely expected, chiefly at the edges where messy outside data comes in, and you let genuine programming mistakes surface loudly so you can fix them. Handling errors well is about expecting the specific, likely failures of real data, not about silencing everything.

What to carry forward

Code that touches real market data must expect mess: missing symbols, blanks, bad numbers. An exception is Python signalling such a failure, and a try block with an except for a specific exception handles it gracefully instead of crashing, as the examples did for a missing key and a zero divisor. Use it at the edges where messy data enters, and let genuine bugs surface loudly.

That completes the core of the language: values and types, strings, lists and dictionaries, conditionals, loops, functions, and handling failure. Part 3 is the turning point, where you bring in the specialised tools, NumPy and pandas, and start working with real market data at scale.