Having learned almost all the basic concepts, now you are entering into somewhat advanced topics. So, fasten your seatbelts and ensure that you have a good grasp of all the topics we have covered so far because it's time to delve into error handling in Python.
While writing programs, we encounter different errors. Not only beginners, we experienced programmers also face them in our daily routine. Avoiding these errors is not possible at any level, so the actual skill is gracefully handling them and preventing them from appearing before the end users. If the errors in the programs are not handled in advance, they can cause inconvenience to the end users. Therefore, in this article, we will explore different types of errors and learn how to handle them efficiently.
Errors and Their Types
Errors are the issues that affect your program execution in one way or another. Before understanding how to handle them, let's explore their different types.
Syntax Errors
These errors occur when you have used the wrong syntax. It includes missing a colon, incorrect indentation, misspelled keywords, unmatched parentheses, etc. When a syntax error occurs, your program does not execute, and the interpreter highlights the code causing the error, specifying the reason behind it. These errors are super simple to resolve.
# Syntax Error
example: missing colon
if True
print("Hello")
# Output: SyntaxError: invalid syntax
Logical Errors
The logical errors occur when there is some fault in the programmer's logic. These errors do not prevent the program from executing but generate unexpected or undesired results. It includes using an incorrect formula, forgetting to specify a terminating point for a loop construct, accidentally using the incorrect operator in conditions, etc. Since these errors do not terminate the program execution or do not prevent it from executing at all, they are incredibly difficult to detect and identify.
# Logical Error example: calculating average
num1 = 10
num2 = 20
num3 = 30
average = num1 + num2 + num3 / 3 # Logical error: division happens before addition
print(average) #
# Output: 40.0 (Incorrect, should be 20.0)
Runtime Errors
These errors occur during program execution and terminate the program with a traceback message stating what went wrong. The code is logically and grammatically correct, but something unexpected happens that Python fails to handle, resulting in halting the program execution. Such unexpected errors are technically termed "Exceptions," and we are going to learn how to handle them in this lesson.
There are numerous built-in exceptions that we usually encounter while writing programs. Some of the most common ones are given below:
- ZeroDivisionError: This occurs when you try to divide a number by 0.
number = 10
print(number/0) # Throws ZeroDivisionError: division by zero Exception
10 + "20" # Throws TypeError: unsupported operand type(s) for +: 'int' and 'str' Exception
number = 10
print(numebr) # Throws NameError: name 'numebr' is not defined. Exception
numbers = [1,2,3,4,5]
print(numbers[5]) # Raises IndexError: list index out of range Exception
users = {1 : "John", 2: "Smith",3 : "Alice"}
print(users[4]) # Raises KeyError: 4 Exception
int("hello")
# Raises ValueError because "hello" cannot be converted to an integer
The try-catch Block: Catching Exceptions
The try-catch block is Python's fundamental exception handling mechanism that allows you to put the code with a doubt of exception inside the try block, and if the exception occurs, you can catch it and handle it gracefully to prevent it from crashing the program.
Syntax:
try:
# Code that might raise an exception
except ExceptionType:
# Code to handle the specific exception if it occurs in the 'try' block
Handling Different Exceptions
Instead of handling general exceptions, it is a good practice to handle specific exceptions to avoid hiding unrelated bugs. Here, I'll share some code examples to handle different exceptions:
Example: ZeroDivisionError
try:
numerator = int(input("Enter your numerator ")) #Taking input from user and converting it to int
denominator = int(input("Enter your denominator: ")) #Taking denominator from user and converting it to int
result = numerator / denominator # dividing numerator by denominator
print("Result = ", result)
except ZeroDivisionError:
print("Error: Cannot divide by zero!")
Sample Output:
Enter your numerator 50
Enter your denominator: 0
Error: Cannot divide by zero!
Example: ValueError
try:
age = int(input("Please enter your age: "))
print("Age: ", age)
except ValueError: # Occurs if the user enters a string or float instead of an integer
print("Invalid input! Please enter a whole number for your age.")
Sample Output:
Please enter your age: 27.5
Invalid input! Please enter a whole number for your age.
Example: Handling Multiple Specific Exceptions at Once
If you doubt that multiple exceptions may occur during program execution, you can specify multiple except blocks, each handling a different exception.
try:
num1 = int(input("Enter first number: "))
num2 = int(input("Enter second number: "))
division_result = num1 / num2
print("Result:", division_result)
except ValueError: # User might enter a non-numeric value
print("Error: Invalid number entered. Please enter integers only.")
except ZeroDivisionError: # User may provide 0 as demominator
print("Error: You cannot divide by zero!")
Handling General Exceptions
If you are unaware of the type of exception that your code may trigger, you can either use a bare except or except exception as e to catch it.
try:
division = 10/0 #Assuming you are unaware of ZeroDivisionError
print("10/0 = ", division)
except Exception as e:
print(f"An unexpected error occurred: {e}")
Or,
try:
division = 10/0 #Assuming you are unaware of ZeroDivisionError
print("10/0 = ", division)
except:
print(f"An unexpected error occurred.")
Although it seems convenient, it is not recommended to use a bare except or general exception since it can hide potential bugs in your program, making it harder to debug. You should only use it when you genuinely want to catch an unforeseen exception and provide a general fallback.
The finally Block
The finally block is used to specify the code that must run regardless of the occurrence of an exception.
Syntax:
try:
# Code that might raise an exception
except SomeError:
# Code to handle the specific exception
finally:
# Code that ALWAYS runs
Example:
isEven = False
try:
number = int(input("Enter a number"))
if number % 2 == 0:
isEven = True
except:
print(f"An unexpected error occurred.")
finally: # Runs even if the exception occurs.
print(isEven)
Great news! You have gained crucial skills in handling unexpected errors in Python with the try-except model. You can now prevent your programs from crashing unexpectedly and show random errors to the users while they try to perform certain actions. In the following article, we will learn about creating functions in Python.