IntroductionSoftware applications don’t run perfectly all the time. Despite intensive debugging and multiple testing levels, applications still fail. Bad data, broken network connectivity, corrupted databases, memory pressures, and unexpected user inputs can all prevent an application from performing normally. When such an event occurs, and the app is unable to continue its normal flow, this is known as an exception. And it's your application's job—and your job as a coder—to catch and handle these exceptions gracefully so that your app keeps working. Show
What Are Python Exceptions?Exceptions in Python applications can happen for many of the reasons stated above and more; and if they aren't handled well, these exceptions can cause the program to crash, causing data loss, or worse, corrupted data. As a Python developer, you need to think about possible exception situations and include error handling in your code. Fortunately, Python comes with a robust error handling framework. Using structured exception handling and a set of pre-defined exceptions, Python programs can determine the error type at run time and act accordingly. These can include actions like taking an alternate path, using default values, or prompting for correct input. This article will show you how to raise exceptions in your Python code and how to address exceptions. Difference Between Python Syntax Errors and Python ExceptionsBefore diving in, it's important to understand the two types of unwanted conditions in Python programming—syntax error and exception. The syntax error exception occurs when the code does not conform to Python keywords, naming style, or programming structure. The interpreter sees the invalid syntax during its parsing phase and raises a SyntaxError exception. The program stops and fails at the point where the syntax error happened. That’s why syntax errors are exceptions that can’t be handled. Here’s an example code block with a syntax error (note the absence of a colon after the “if” condition in parentheses):
The interpreter picks up the error and points out the line number. Note how it doesn’t proceed after the syntax error:
On the other hand, an exception happens when the code has no syntax error but encounters other error situations. These conditions can be addressed within the code—either in the current function or in the calling stack. In this sense, exceptions are not fatal. A Python program can continue to run if it gracefully handles the exception. Here is an example of a Python code that doesn’t have any syntax errors. It’s trying to run an arithmetic operation on two string variables:
The exception raised is TypeError:
Python throws the TypeError exception when there are wrong data types. Similar to TypeError, there are several built-in exceptions like:
You can refer to the Python documentation for a full list of exceptions. How to Throw an Exception in PythonSometimes you want Python to throw a custom exception for error handling. You can do this by checking a condition and raising the exception, if the condition is true. The raised exception typically warns the user or the calling application. You use the “raise” keyword to throw a Python exception manually. You can also add a message to describe the exception Here is a simple example: Say you want the user to enter a date. The date has to be either today or in the future. If the user enters a past date, the program should raise an exception: Python Throw Exception Example
To test the code, we enter a date older than the current date. The “if” condition evaluates to true and raises the exception:
Instead of raising a generic exception, we can specify a type for it, too:
With a similar input as before, Python will now throw this exception:
Using AssertionError in Python Exception ThrowingAnother way to raise an exception is to use assertion. With assertion, you assert a condition to be true before running a statement. If the condition evaluates to true, the statement runs, and the control continues to the next statement. However, if the condition evaluates to false, the program throws an AssertionError. The diagram below shows the logical flow: Using AssertionError, we can rewrite the code snippet in the last section like this:
Note how we removed the “if” condition and are now asserting that the date provided is greater than or equal to the current date. When inputting an older date, the AssertionError displays:
Catching Python Exceptions with Try-ExceptNow that you understand how to throw exceptions in Python manually, it’s time to see how to handle those exceptions. Most modern programming languages use a construct called “try-catch” for exception handling. With Python, its basic form is “try-except”. The try-except block looks like this: Python Try Catch Exception Example
Here, the program flow enters the “try” block. If there is an exception, the control jumps to the code in the “except” block. The error handling code you put in the “except” block depends on the type of error you think the code in the “try” block may encounter. Here’s an example of Python’s “try-except” (often mistakenly referred to as “try-catch-exception”). Let’s say we want our code to run only if the Python version is 3. Using a simple assertion in the code looks like this:
If the of Python version is not 3, the error message looks like this:
Instead of letting the program fail with an unhandled exception and showing an ugly error message, we could use a try-except block for a graceful exit.
Now, the error message is much cleaner: Python version must be 3 The “except” keyword in the construct also accepts the type of error you want to handle. To illustrate this, let’s go back to our date script from the last section. In that script, we assumed the user will enter a date in “YYYY-MM-DD” format. However, as a developer, you should cater to any type of erroneous data instead of depending on the user. For example, some exception scenarios can be:
To address all these conditions, we can rewrite the code block as shown below. This will catch any ValueError exception raised when meeting any of the above conditions:
In this case, the program will exit gracefully if the date isn’t correctly formatted. You can include multiple “except” blocks for the “try” block to trap different types of exceptions. Each “except” block will address a specific type of error:
Here’s a very simple example:
We can test this program with different values:
Catching Python Exceptions with Try-Except-ElseThe next element in the Python “try-except” construct is “else”: Python Try Except Else Example
The “else” block runs if there are no exceptions raised from the “try” block. Looking at the code structure above, you can see the “else” in Python exception handling works almost the same as an “if-else” construct To show how “else” works, we can slightly modify the arithmetic script’s code from the last section. If you look at the script, you will see we calculated the variable value of “result” using an arithmetic expression. Instead of putting this in the “try” block, you can move it to an “else” block. That way, the exception blocks any error raised while converting the input values to integers. And if there are no exceptions, the “else” block will perform the actual calculation:
Using simple integers as input values runs the “else” block code:
And using erroneous data like empty values, decimal numbers, or strings cause the corresponding “except” block to run and skip the “else” block:
However, there’s still a possibility of unhandled exceptions when the “else” block runs:
As you can see, both inputs are integers (1 and 0), and the “try” block successfully converts them to integers. When the “else” block runs, we see the exception. So how do you handle errors in the “else” block? You guessed that right—you can use another “try-except-else” block within the outer “else” block:
Catching Python Exceptions with Try-Except-Else-FinallyFinally, we have the last optional block in Python error handling. And it’s literally called “finally”: Python Try Finally Example
The “finally” block runs whether or not the “try” block’s code raises an exception. If there’s an exception, the code in the corresponding “except” block will run, and then the code in the “finally” block will run. If there are no exceptions, the code in the “else” block will run (if there’s an “else” block), and then the code in the “finally” block will run. Since the code in the “finally” block always runs, you want to keep your “clean up” codes here, such as:
Here’s an example of using “finally”:
Here, the “try” block tries to open a file for reading. If the file doesn’t exist, the exception block shows a warning message, creates the file, and adds a static value of “2” to it. If the file exists, the “else” block reads the first line of its content and prints that out. Finally, the “finally” block closes the file. This happens whether or not the file initially existed. What we have discussed so far can be summarized in the flowchart below: How Rollbar Can Help Log and Track Python ErrorsRollbar is a continuous code improvement platform for software development teams. It offers an automated way to capture Python errors and failed tests in real time from all application stack layers and across all environments. This allows creating a proactive and automated response to application errors. The diagram below shows how Rollbar works: Rollbar natively works with a wide array of programming languages and frameworks, including Python. Python developers can install pyrollbar, Rollbar’s SDK for Python, using a tool like pip, importing the Rollbar class in the code, and sending Python exceptions to Rollbar. The code snippet below shows how easy it is:
Track, Analyze and Manage Errors With RollbarManaging errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing errors easier than ever. Try it today. |