How to catch all exceptions in Python

How to catch all exceptions in Python

Iryne Somera Developer Tips, Tricks & Resources

One of the struggles developers face is how to catch all Python exceptions. Developers often categorize exceptions as coding mistakes that lead to errors when running the program. Some developers still fail to distinguish between errors and exceptions.

In the case of Python application development, a python program terminates as soon as it encounters an unhandled error. So, to establish the difference between errors and exceptions, there are two types of errors:

  • Syntax errors
  • Logical errors (Exceptions)

First, let’s examine the syntax errors. Python syntax errors are caused by not following the proper structure (syntax) of the language. It is also known as a parsing error.

Here’s an example:

>>> ages = {

    ‘jj’: 2,

    ‘yoyo’: 4

}

print(f’JJ is {ages[“jj”]} years old.’)

The output:

JJ is 2 years old.

This is a simple code with no syntax error. Then we will add another variable tomtom:

>>> ages = {

    ‘jj’: 2,

    ‘yoyo’: 4

    ‘tomtom’: 6

}

print(f’JJ is {ages[“jj”]} years old.’)

Upon inspection, you can see an invalid syntax on the second entry, yoyo, inside the array with a missing comma. Try to run this code, and you will get a traceback:

File “<pyshell>”, line 1

    >>> ages = {

     ^

SyntaxError: invalid syntax

As you notice, the traceback message didn’t pinpoint the exact line where the syntax error occurs. The Python interpreter only attempts to locate where the invalid syntax is. It only points to where it first noticed the problem. So, when you get a SyntaxError traceback, it means that you should visually inspect whether the interpreter is pointing to the right error.

In the example above, the interpreter encounters an invalid syntax inside an array called ages. Thus, it points out that there is something wrong inside the array.

This is a syntax error. 

In most cases, a Python developer writes an impressive piece of code that is ready to execute. The program becomes a robust machine learning model, but during execution, Python throws up an unexpected error. Unfortunately, it is no longer the typical syntax error. Developers are now dealing with logical errors, also known as exceptions.

Let’s delve into exceptions.


New call-to-action

Exceptions in Python

Exceptions are errors that occur at runtime. Mostly, these errors are logical. For example, when you try to divide a number by zero, you will get a ZeroDivisionError. When you open a file(read) that doesn’t exist, you will receive FileNotFoundError. Further, when you try to import a module that doesn’t exist, you will get ImportError.  

Here is how Python treats the above-mentioned errors:

ZeroDivisionError

>>> 2 / 0

Traceback (most recent call last):

  File “<pyshell>”, line 1, in <module>

ZeroDivisionError: division by zero

FileNotFoundError

>>> open(“stack.txt”)

Traceback (most recent call last):

  File “<pyshell>”, line 1, in <module>

FileNotFoundError: [Errno 2] No such file or directory: ‘stack.txt’

ImportError

>>> from collections import qwerty

Traceback (most recent call last):

  File “<pyshell>”, line 1, in <module>

ImportError: cannot import name ‘qwerty’ 

Whenever a runtime error occurs, Python creates an exception object. It then creates and prints a traceback of that error with details on why the error happened.

Here are common exceptions in Python:

  • IndexError – You will get this error when an index is not found in a sequence. For instance, accessing the 6th index when the length of the list is only five(5). 
  • IndentationError – Happens when indentation is not specified correctly.
  • ValueError – Occurs when the built-in function for a data type has the valid type of arguments, but the arguments have invalid values. 
  • IOError – Developers often encounter this error when an input/output operation fails.
  • Arithmetic Error – Occurs when numeric calculations fail.
  • Floating-point Error – Happens when a floating-point calculation fails.
  • Assertion Error – Occurs when there is assert statement failure.
  • Overflow Error – Developers get this error if the result of an arithmetic operation is too large and becomes machine unreadable. 
  • Type Error – Happens when an incorrect type of function or operation is applied to an object.

You can visit the official Python documentation site to have in-depth knowledge about Python built-in exceptions. While the Python community offers great support, Python application deployment discussions can be improved. Application Performance Management (APM) like Retrace, is a great tool to deal with Python exceptions. It helps you find all the exceptions thrown and identify its root cause. You can try it for free today!

Catching Exceptions in Python

A direct logic is followed to catch exceptions in Python. When an exception occurs, the Python interpreter stops the current process. It is handled by passing through the calling process. If not, the program will crash.

For instance, a Python program has a function X that calls function Y, which in turn calls function Z. If an exception exists in function Z but is not handled within Z, the exception passes to Y and then to X. Simply, it will have a domino effect. 

An unhandled exception displays an error message and the program suddenly crashes. To avoid such a scenario, there are two methods to handle Python exceptions:

  1. Try – This method catches the exceptions raised by the program
  2. Raise – Triggers an exception manually using custom exceptions

Let’s start with the try statement to handle exceptions. Place the critical operation that can raise an exception inside the try clause. On the other hand, place the code that handles the exceptions in the except clause.

Developers may choose what operations to perform once it catches these exceptions. Take a look at the sample code below:

import sys

list = [‘x’, 1e-15, 5]

for result in list:

    try:

        print(“The result is”, result)

        y = 1/int(result)

        break

    except:

        print(“Whew!”, sys.exc_info()[0], “occurred.”)

        print(“Next input please.”)

        print()

print(“The answer of”, result, “is”, y)

The program has an array called list with three elements. Next, the line that causes an exception is placed inside the try block. If there are no exceptions, the except block will skip, and the logic flow will continue until the last element. However, if an exception occurs, the except block will catch it. 

The output:

The result is x

Whew! <class ‘ValueError’> occurred.

Next input, please.

The result is 1e-15

Whew! <class ‘ZeroDivisionError’> occurred.

Next input, please.

The result is 5

The answer to 5 is 0.2

To print the name of the exception, we use the exc_info()function inside the sys module. The first two elements cause exceptions since an integer can’t be divided with string and a zero value. Hence, it raised ValueError and ZeroDivisionError exceptions.

Catching Specific Exceptions in Python

What if you want to deal with a specific exception? In the previous example, it didn’t mention any specific exception in the except block. That is not a good programming practice because it will catch all exceptions. 

Additionally, it will handle all exceptions in the same manner, which is an incorrect approach. Therefore, maximize the use of the except block and specify which exceptions it should catch.

To execute this concept, we can use a tuple of values to specify multiple exceptions. Here is a sample pseudo-code:

try:

   #do something

   #your statements

   pass

except Exception_1:

   #handle Exception_1 and execute this block statement

   pass

except Exception_2:

   handle Exception_2 and execute this block statement

   pass

except Exception_3:

   #handle Exception_3 and execute this block statement

   pass

except:

   #handles all other exceptions

   pass

Raising Exceptions in Python

Another way to catch all Python exceptions when it occurs during runtime is to use the raise keyword. It is a manual process wherein you can optionally pass values to the exception to clarify the reason why it was raised.

>>> raise IndexError

Traceback (most recent call last):

  File “<pyshell>”, line 1, in <module>

IndexError

>>> raise OverflowError(“Arithmetic operation is too large”)

Traceback (most recent call last):

  File “<pyshell>”, line 1, in <module>

OverflowError: Arithmetic operation is too large

Let’s have a simple code to illustrate how raise keyword works:

try:

     x = int(input(“Enter a positive integer: “))

     if x <= 0:

         raise ValueError(“It is not a positive number!”)

except ValueError as val_e:

    print(val_e)

The output:

Enter a positive integer: -6

It is not a positive number!

Enter a positive integer: 6

Python try with else clause

In dealing with exceptions, there are instances that a certain block of code inside try ran without any errors. As such, use the optional else keyword with the try statement.

Here is a sample code:

try:

    number = int(input(“Enter a number: “))

    assert number % 2 == 0

except:

    print(“This is an odd number!”)

else:

    print(“This is an even number!”)

    rem = number % 2

    print(“The remainder is “, rem)

The output:

Enter a number: 3

This is an odd number!

Enter a number: 2

This is an even number!

The remainder is 0

Python try 

The try statement in Python has an optional finally block. It means that it executes the block by all means. At the same time, it releases external resources. 

Some examples include a connection between a mobile app and a remote data center via a distributed network. All resources should be clean once the program stops, whether it successfully runs or not. 

It is the job of the finally block to guarantee execution. Such actions include closing a file or GUI  and disconnecting from the network.

Check on the example below to illustrate how the operation works:

try:

   file = open(“myFile.txt”,encoding = ‘utf-8’)

   # this performs file operations

finally:

   f.close()

The f.close()function ensures that the file is closed even if an exception happens during the program execution.

Advantages of Exception Handling and Using the right APM

Bugs and errors are part of every developer’s journey. As mentioned above, errors and exceptions are different. So, why is it that Python developers should know how to catch Python exceptions and master exception handling? 

The answers to this are not theoretical. Instead, let’s have a sample use case.

For example, you’re dealing with a vast amount of data. So, you build a program that reads thousands of files across multiple directories. There is no way that you will not encounter an error here. Possible errors may include wrong or missing file type, invalid file format, or dealing with different file extensions. 

On that note, it is not feasible to open all the files and write a script that can cater to it accordingly. With exception handling, developers can define multiple conditions. For instance, resolve an invalid format by establishing the correct format first and then reading the file afterward. 

Another option is to continue reading the data and skip those files with an invalid format.  Then, create a log file that can deal with it later.  To help you with log files, APMs like Retrace is a great tool in dealing with logs. It has logging features and actionable insights to support you with your Python applications.

About Iryne Somera

Iryne Somera is a professor in the Department of Computer Engineering. She loves to research and write articles related to computing technology such as Computer Hardware Fundamentals, Management Information Systems, Software Development and Project Management. In her spare time, she loves to experiment in her kitchen with her healthy breakfast ideas.