‘try…catch’ in Python: It’s Called ‘try…except’ (Error Handling Guide)

Try Catch in Python
Error handling in Python. Image design by Elias Ervast

Error handling is an important aspect of coding. When errors are treated properly, the programs operate smoothly and cause no annoying crashes for the end users. In Python, error handling happens with a try-except code construct. (If you come from another programming language, there is no such thing as a try-catch statement in Python.)

The try-except code works such that it tries to run an expression or a piece of code. If the run fails, Python proceeds to run the actions in an except block. If the run succeeds, no further action is taken.

As a quick example, let’s try to print an undefined value and show an error if it fails:

try:
  print(x)
except:
  print("Exception thrown. x does not exist.")

Output:

Exception thrown. x does not exist.
  • Here the program tries to run the code inside the try block.
  • If (and when) it fails, the except block catches the exception and logs it into the console.

This is a definitive guide to handling errors in Python. You will learn how to use the try…except structure for dealing with exceptions in your code. Besides, you learn how to handle multiple exceptions and how to add finally and else blocks in the error-handling code to always run actions. All the theory is backed up with great and illustrative examples.

Let’s jump into it!

What Is Error Handling in Coding?

Whenever you’re writing software code, there’s always a chance of something going wrong.

For example, if you expect a user to enter a number but they enter text instead, the program can crash if you haven’t prepared for such a faulty input.

Error handling is an important part of writing code that maintains the normal flow of your program without crashes and other annoyances.

If you’ve ever used a mobile app, and all of a sudden the app closes without warnings, there’s an unhandled error behind the scenes. It could be that the software code tries to read a value that doesn’t exist. Nonetheless, this is super annoying for the end users of your application, isn’t it?

When writing software code, you should always keep in mind what errors might occur to avoid the program causing annoying crashes.

As an example, if a Python function operates on the assumption that an input value is always an integer, it could lead to a crash if the input happens to be a string. To avoid crashes like this, you need to write the code such that it knows what to do if someone accidentally inputs a string instead of an integer.

This is where error handling helps. In Python, you can do error handling with a simple try-except code structure. The idea is to try to run a piece of code. If the trial fails, then the except block handles the error instead of letting the program crash.

Try-Except Pattern in Python Error Handling

In Python, you can use try-except statements to handle errors and exceptions that might happen when you run code.

Errors that take place during the execution of a program are called exceptions. In Python, faulty expressions raise errors and exceptions that will crash your program if you don’t handle the exceptions properly.

For example, a classic example of an exception is when you try to access an undefined value or divide a number by 0.

An abrupt crash is not beneficial for you as a developer needless to mention for the end users of your applications.

This is where the built-in error-handling mechanism helps. Instead of letting your program crash, you handle the errors during runtime and the program execution continues.

The error handling pattern in Python consists of the following:

  • The try block. It runs a piece of code. If this piece of code fails, an exception is raised.
  • The except block. This block catches the possible error raised by the try block. Also, you can (and should) specify the type of error you’re expecting from the try block here.
  • The optional finally block runs a piece of code regardless of whether there were errors or not. This is an optional block of code you don’t need in the error handling scheme.

Here’s what a generic try except code structure looks like:

try:
    <actions>
except Exception:
    <handle the exception here>

This code is pretty intuitive to read. The try specifies a block of code that Python tries to run. If the run fails, the except block catches an exception and runs some code.

Example

As an example, let’s run a try-except code to make sure the code doesn’t crash if a variable x is not defined:

try:
  print(x)
except:
  print("Exception thrown. x does not exist.")

Notice that even though this piece of code prevents it from crashing, the way it’s written right now is bad practice. This is because we don’t define the type of error we expect in the except block.

Specify Error Type

To fix the earlier example, you need to know that when you’re accessing an undefined variable in Python, you should expect it to cause a NameError.

Now you can expect a potential NameError in the except block:

try:
  print(x)
except NameError:
  print("NameError: x is not defined.")

Output:

NameError: x is not defined.

This not only makes the code more readable but also ensures you know what you’re doing. It’s much better to specify the type (or types) of error you might face instead of just catching a generic error.

Now, what if there is more than one exception that might occur? No problem. Python lets you define as many except blocks as needed.

Multiple Exceptions in Python Error Handling

In Python, you can have multiple except blocks for handling different types of errors separately.

try:
    <do something>
except Exception1:
    <handle the this error type>
except Exception2:
    <handle the this error type>
except Exception3:
    <handle the this error type>

This is best demonstrated with an example.

Example

Let’s create a script that divides two numbers by one another. When it comes to dividing numbers, there are two things that could go wrong:

  1. One or both of the numbers are not defined.
  2. The denominator is zero.

The first problem will raise a NameError. The second issue causes a ZeroDivisionError.

To prevent crashes caused by these two potential issues, you need to handle both types of errors in your code. To do this, let’s specify some try-except error-handling logic in the code.

In the try-except structure, you want to handle both exceptions separately. Thus, you need two except blocks for the different cases:

try:
    result = x / y
except ZeroDivisionError:
    print("Make sure no divisions by 0 are made.")
except NameError:
    print("Make sure both numbers are defined.")

By the way, feel free to copy-paste the above code into your code editor and run the code to see what happens.

Now, because x and y are not defined, the program won’t crash thanks to the error handling you did. Instead, the program will print the message you specified that will be shown in case of a NameError:

Make sure both numbers are defined

Now, let’s define x and y, but let’s make y zero:

x = 10
y = 0

try:
    result = x / y
except ZeroDivisionError:
    print("Make sure no divisions by 0 are made.")
except NameError:
    print("Make sure both numbers are defined.")

Because dividing by 0 is mathematically not possible, this causes an error. But thanks to your careful error handling, this error doesn’t crash the program. Instead, it shows there was an error dividing by 0:

Make sure no divisions by 0 are made.

Finally, let’s write the code in a way that there are no longer errors:

x = 10
y = 5

try:
    result = x / y
except ZeroDivisionError:
    print("Make sure no divisions by 0 are made.")
except NameError:
    print("Make sure both numbers are defined.")

Now there is no error message. This means the program ran successfully because both x and y were defined and y was not 0.

Finally Block in Python Error Handling

In Python, you can add a finally block in the try-except error handling code. The finally block is an optional block that runs regardless of whether there were errors or not.

For instance, let’s run a function that does error handling without the finally block:

def run():
   try:
      print(x)
   except:
      print("There was an error")
      return None
   print("Yay")
   
run()

Output:

There was an error

Notice that the function never prints “Yay” because it returns before.

To print the “Yay” part of the code, you need to add a finally block in the error handling structure. The finally block will run no matter what. Even if the function returns a value, the finally block will run and finish what it has to in the error handling code.

def run():
   try:
      print(x)
   except:
      print("There was an error")
      return None
   finally:
      print("Yay")
   
run()

Output:

There was an error
Yay

Else Block in Python Error Handling

You can also add an optional else block after except blocks in Python. The idea of an else block is to run code if there were no errors in the error handling sequence.

For example, let’s divide two numbers by one another, catch potential errors, and print a success message if no errors were thrown.

x = 15
y = 5

try:
    print(x / y)
except ZeroDivisionError:
    print("Make sure no divisions by 0 are made.")
else:
    print("There were no errors.")

Conclusion

In Python, there is no such thing as a try-catch statement. Instead, Python has its own version called try-except. The try-except code structure is used to deal with errors and exceptions.

Here is an example:

try:
  print(x)
except:
  print("x is not defined")
finally:
  print("Process finished")

Output:

x is not defined
Process finished

Thanks for reading. Happy coding!

Further Reading