Exceptions in Python programs can occur for various causes, and if they aren’t handled properly, they can cause the program to crash, resulting in data loss or, worse, data corruption. As a Python programmer, you must consider various exception scenarios and incorporate error management into your code.
Python, fortunately, includes a sophisticated error handling system. Python programs can establish the error type at run time using structured exception handling and a collection of pre-defined exceptions. These activities include taking a different path, using default settings, or urging for accurate input. This article will show you how to handle exceptions and raise them in your Python code.
Python Syntax Errors and Python Exceptions: What’s the Difference?
Before we get started, it’s crucial to understand the two types of undesirable situations that might occur in Python programming: syntax errors and exceptions.
The syntax error exception is thrown when the code does not follow Python keywords, naming conventions, or programming structure. During the parsing process, the interpreter notices the improper syntax and throws a SyntaxError exception. The program comes to a halt and fails where the syntax mistake occurs. As a result, syntax errors are treated as unhandled exceptions. Here’s an example code block with a syntax issue (notice the lack of a colon after the parenthesized “if” condition):
val_one = 23 val_two = 37 if (val_one < val_two) print('val_one is less than val_b') val_three= 45 print (val_three)
The interpreter detects the mistake and displays the line number. It’s worth noting how it doesn’t continue after the syntax error:
On the other hand, an exception occurs when the code contains no syntax errors but encounters other errors. These problems can be solved in the code, either in the current function or the calling stack. Exceptions aren’t fatal in this sense. If a Python program gracefully handles an exception, it can continue to run. Here’s an example of Python code that’s free of syntactic mistakes. It’s attempting to perform arithmetic on two string variables:
val_one = 'code' val_two = 'under' print (val_one % val_two)
According to the image below, the exception raised is a TypeError:
When there are incorrect data types, Python throws the TypeError exception. There are various built-in exceptions, similar to TypeError. These include:
How to throw an exception in Python
For error handling, you may wish Python to throw a custom exception. It is accomplished by testing a condition and raising an exception if it is true. The user or calling program is usually notified when an exception is raised. To manually throw a Python exception, use the “raise” keyword. You can also include a message to explain why the exception occurred. Here’s an easy example: Suppose you want the user to enter a date. Either today or in the future must be the date. If the user types in date from the past, the software should throw an exception:
from datetime import datetime date_now = datetime.now() print ("The date now is: " + date_now.strftime('%Y-%m-%d')) fetch_date_input = input("Enter date in yyyy-mm-dd format: ") """ Here, we're not checking for date input format. """ given_date = datetime.strptime(fetch_date_input , '%Y-%m-%d') print ("The given date is: " + given_date.strftime('%Y-%m-%d')) if (given_date.date() < date_now.date()): raise Exception(" You cannot provide a Date in the past")
We use a date older than the current date to test the code. When the “if” condition evaluates to true, the following exception is thrown:
We may also specify a type for it instead of issuing a general exception:
if (given_date.date() < date_now.date()): raise ValueError("You cannot provide a Date in the past")
Python will now throw the following exception with the same input as before:
Exception Throwing with AssertionError in Python
The assertion is another approach to raise an exception. Before running a statement, you assert that a condition is true with assertion. If the condition is true, the statement is executed, and control moves on to the following sentence. On the other hand, the program throws an AssertionError if the condition evaluates to false. We can modify the code sample in the previous section using AssertionError as follows:
from datetime import datetime date_now = datetime.now() print ("The date now is: " + date_now.strftime('%Y-%m-%d')) fetch_date_input = input("Enter date in yyyy-mm-dd format: ") """ We are not checking for the date input format here """ given_date = datetime.strptime(fetch_date_input, '%Y-%m-%d') print ("The given date is: " + given_date.strftime('%Y-%m-%d')) assert(given_date.date() >= date_now.date()), "You cannot provide a Date in the past"
Notice how the “if” condition has been removed, and we are now stating that the date provided is larger than or equal to the current date. The AssertionError appears when you enter an older date:
Using Try-Except to Catch Python Exceptions
Now that you know how to throw exceptions in Python manually, it’s time to look at how to deal with them. Most current programming languages employ the “try-catch” construct for exception management. The most basic form in Python is “try-except.” This is how the try-except block looks:
try: <--program code--> except: <--exception handling code--> <--program code--->
The program flow enters the “try” block at this point. If an exception occurs, control is passed to the code in the “except” block. The error handling code in the “except” block is determined by the sort of error you believe the code in the “try” block will encounter.
Here’s an example of Python’s “try-except” (sometimes called “try-catch-exception” by mistake). Let’s imagine we only want our code to run if Python is version 3. The following is an example of how to use a simple assertion in the code:
import sys assert (sys.version_info == 3), "Python version 3 is required. "
If the Python version is not 3, an error message appears.
We could use a try-except block for a graceful departure instead of letting the program die with an unhandled exception and displaying an unsightly error message. The error message is now much more concise:
import sys try: assert (sys.version_info == 3), "Python version 3 is required. " except Exception as e: print (e)
The construct’s “except” keyword also allows the type of mistake you want to manage. Let’s return to our date script from the last section to demonstrate this. We thought the user would submit the date in the format “YYYY-MM-DD” in that script. Instead of relying on the user, you should cater to any form of erroneous data as a developer. The following are some examples of exception scenarios:
- Number entered
- Time entered
- No date entered (blank)
- Text entered
- Different date formats entered (such as “dd/mm/yyyy”)
- Special characters entered
We can update the code block as shown below to address all of these scenarios. This will catch any ValueError exceptions thrown when any of the following conditions are met:
from datetime import datetime date_now = datetime.now() print ("The date now is: " + date_now.strftime('%Y-%m-%d')) fetch_date_input = input("Enter date in yyyy-mm-dd format: ") try: given_date = datetime.strptime(fetch_date_input, '%Y-%m-%d') except ValueError as err: print(err) exit() print ("The given date is: " + given_date.strftime('%Y-%m-%d')) assert(given_date.date() >= date_now.date()), "You cannot provide a Date in the past"
If the date isn’t formatted correctly, the software will gracefully leave in this scenario. You can use numerous “except” blocks in the “try” block to catch distinct types of errors. Each “unless” block will deal with a different kind of error:
... try: <--program code--> except <--First Exception -->: <--exception handling code--> except <-- Second Exception -->: <--exception handling code--> except <-- Third Exception-->: <--exception handling code--> …
starting_num = 50 try: val_one = input("Enter 1st number:") val_two = input("Enter 2nd number:") calc_result = (int(val_one) * int(val_two))/(starting_num * int(val_two)) except TypeError as typeError: print(typeError) exit() except ZeroDivisionError as zeroDivisionError: print(zeroDivisionError) exit() except ValueError as valError: print(valError) exit() except: print('Error Occurred Unexpectedly!') exit() print (calc_result)
Software applications do not always run flawlessly. Even after extensive debugging and several levels of testing, apps continue to fail. Bad data, lost network connectivity, corrupted databases, memory pressures, and unexpected user inputs can all cause an application to fail to function properly. An exception happens when such an event occurs, and the program cannot resume its normal flow. And it’s up to your app — and you as a coder — to catch and elegantly manage these exceptions, so your app keeps running.