Python Diaries ….. Day 12

Error Handling 🛠 🛠 🛠

Nishitha Kalathil
5 min readSep 20, 2023

--

Welcome to Day 12 of Python Diaries! Today, we’ll be exploring the important topic of error handling in Python. Error handling allows you to gracefully handle exceptions or errors that may occur during the execution of your code, preventing them from causing your program to crash.

What is Error Handling?

Error handling is the process of anticipating, detecting, and responding to errors that might occur in your code. In Python, errors are known as exceptions, and they can be caused by a variety of reasons, such as incorrect input, unexpected behavior, or problems with external resources.

Types of Errors

There are three main types of errors in Python:

  1. Syntax Errors:
  • These are errors that occur when the code is not written in a valid Python syntax. They are detected by the Python interpreter when it tries to parse your code.
if x > 5
print("x is greater than 5")

output:

Cell In[1], line 1
if x > 5
^
SyntaxError: expected ':'

2. Logical Errors:

  • These errors occur when the code is syntactically correct, but it does not produce the expected result due to a mistake in the logic.
def add_numbers(x, y):
return x - y # Should be x + y

3. Runtime Errors (Exceptions):

  • These errors occur during the execution of the code. They are also known as exceptions and can be handled using try-except blocks.
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"Error: {e}")

Exceptions

When an exceptional situation arises, an object representing that situation is created (an exception), and the program flow is altered to handle it.

There are many built-in exception types in Python, such as SyntaxError, TypeError, ValueError, FileNotFoundError, and many more. Each type of exception represents a different kind of error that can occur during the execution of a program.

SyntaxError: Raised when there is a syntax error in your code (e.g., a typo, missing parenthesis, or incorrect indentation).

# Example with a missing closing parenthesis
try:
result = (4 + 2
except SyntaxError as e:
print(f"SyntaxError: {e}")

IndentationError: Raised when there is an issue with the indentation of your code (e.g., mixing tabs and spaces).

# Example with inconsistent indentation
try:
if True:
print("Indented incorrectly")
except IndentationError as e:
print(f"IndentationError: {e}")

NameError: Raised when a local or global name is not found (i.e., a variable or function name is not defined in the current scope).

# Example with an undefined variable
try:
result = x + 2
except NameError as e:
print(f"NameError: {e}")

TypeError: Raised when an operation or function is applied to an object of inappropriate type.

# Example with trying to add incompatible types
try:
result = "2" + 2
except TypeError as e:
print(f"TypeError: {e}")

ValueError:

Raised when a function receives an argument of the correct data type, but with an inappropriate value.

# Example with converting an inappropriate value to int
try:
result = int("abc")
except ValueError as e:
print(f"ValueError: {e}")

IndexError: Raised when you try to access an index that doesn’t exist in a list, tuple, or other sequence.

# Example with accessing an index that doesn't exist
try:
my_list = [1, 2, 3]
result = my_list[3]
except IndexError as e:
print(f"IndexError: {e}")

KeyError: Raised when you try to access a dictionary with a key that doesn’t exist.

# Example with accessing a non-existent key in a dictionary
try:
my_dict = {'a': 1, 'b': 2}
result = my_dict['c']
except KeyError as e:
print(f"KeyError: {e}")

FileNotFoundError: Raised when an attempt to open a file fails because the file cannot be found.

# Example with trying to open a non-existent file
try:
with open('nonexistent_file.txt', 'r') as file:
content = file.read()
except FileNotFoundError as e:
print(f"FileNotFoundError: {e}")

PermissionError: Raised when you try to access a file or resource without the necessary permissions.

# Example with trying to open a file without proper permissions
try:
with open('/root/some_file.txt', 'w') as file:
file.write("Some data")
except PermissionError as e:
print(f"PermissionError: {e}")

ZeroDivisionError: Raised when you try to divide a number by zero.

# Example with dividing by zero
try:
result = 5 / 0
except ZeroDivisionError as e:
print(f"ZeroDivisionError: {e}")

Raising Exceptions

You can explicitly raise an exception using the raise statement. This is useful when you want to signal that a certain condition has occurred that requires special handling.

if condition_not_met:
raise ValueError("Invalid input")

Catching Exceptions

To handle exceptions, you use a try-except block. The code that might raise an exception is placed in the try block. If an exception occurs, the code in the except block is executed.

try:
# Code that might raise an exception
except SomeException as e:
# Code to handle the exception

SomeException is the type of exception you expect to occur. You can catch specific exceptions or use a broader Exception class to catch any exception.

try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"Error: {e}")

Handling Multiple Exceptions:

You can handle multiple types of exceptions by using multiple except blocks or by using a tuple of exception types in a single except block.

try:
# Code that might raise an exception
except (ExceptionType1, ExceptionType2) as e:
# Code to handle ExceptionType1 or ExceptionType2

Example with multiple blocks:

try:
file = open("nonexistent_file.txt", "r")
except FileNotFoundError as e:
print(f"Error: {e}")
except IOError as e:
print(f"IO Error: {e}")

you can change it as follows:

try:
file = open("nonexistent_file.txt", "r")
except (FileNotFoundError, IOError) as e:
print(f"Error: {e}")

else and finally Blocks:

You can optionally include an else block after the try block. Code in the else block will be executed if no exceptions are raised.

The finally block is used for code that should be executed regardless of whether an exception occurred or not. This block is often used for cleanup operations.

try:
# Code that might raise an exception
except SomeException as e:
# Code to handle the exception
else:
# Code to execute if no exceptions were raised
finally:
# Code to execute regardless of exceptions

Custom Exceptions:

You can create your own exception classes by inheriting from the built-in Exception class. This allows you to define specific types of exceptions that are relevant to your application.

class CustomError(Exception):
pass

try:
if condition_not_met:
raise CustomError("Custom error message")
except CustomError as e:
# Handle the custom exception

Logging Exceptions:

You can log exceptions using the logging module, which allows you to record information about when and where an exception occurred.

import logging

try:
# Code that might raise an exception
except SomeException as e:
logging.exception("An error occurred")

Error handling is a crucial aspect of writing robust and reliable Python code. It allows you to gracefully handle exceptions and prevent them from causing your program to crash. By using try-except blocks, you can anticipate and respond to different types of errors that may occur during the execution of your code. You can access the other topics in this tutorial series right here:

In Day 13, we’ll explore the concept of Regular expressions. Keep up the great work! Happy coding!

--

--