Errors and Exception


In Python programming, errors are issues that occur during the execution of a program, preventing it from running as expected. Python categorizes errors into three main types:

Syntax Errors:

Syntax errors, also known as parsing errors, occur when the Python parser detects an error in the syntax of the code. These errors prevent the program from running and are usually identified during the parsing phase before the program starts executing. Common syntax errors include missing parentheses, incorrect indentation, misspelled keywords, or using an invalid operator.

# Syntax Error Examples
print("Hello, world!"  # Missing closing parenthesis
if x == 5              # Missing colon

Runtime Errors (Exceptions):

Runtime errors, also called exceptions, occur during the execution of a Python program. These errors disrupt the normal flow of the program and can cause it to terminate abruptly unless they are handled properly using exception handling mechanisms. Runtime errors can happen due to various reasons, such as division by zero, accessing an invalid index in a list, or trying to open a file that does not exist.

# Runtime Error Examples
x = 10 / 0                # Division by zero
my_list = [1, 2, 3]
print(my_list[5])          # Index out of range
file = open("nonexistent_file.txt")  # FileNotFoundError

Semantic Errors:

Semantic errors occur when the code runs without raising any syntax or runtime errors but does not produce the expected result due to logical flaws or incorrect understanding of the problem domain. These errors are often challenging to detect because the code executes without any apparent issues, but it produces incorrect outcomes.

# Semantic Error Example
# This function is intended to calculate the area of a rectangle,
# but it uses the wrong formula.
def calculate_area(length, width):
    return length * width * 2

Exception Handling in Python

Exceptions are the run time errors. Here is the detail concept related to exception handling in python

Purpose:

The main purpose of handling exception in python are:

  • Prevents program crashes when unexpected occurrences (exceptions) arise.
  • Enables graceful program recovery or user-friendly error reporting.

Key Concepts:

Following are the key concepts and keywords used to handle runtime errors in python programming: 

  • try block: Contains code susceptible to exceptions.
  • except block: Handles specific exceptions, or all with except:.
  • else block: Executes if no exception occurs in the try block.
  • finally block: Always executes, regardless of exceptions.

Common Exceptions:

Following are the most commonly occurring runtime errors: 

  • ZeroDivisionError: Division by zero.
  • TypeError: Incorrect operand type for an operation.
  • NameError: Undefined variable or function name.
  • IndexError: Index out of bounds for a list, string, or other sequence.
  • ValueError: Invalid value for a function or operation.
  • KeyError: Key not found in a dictionary.
  • FileNotFoundError: Attempt to open a non-existent file.
  • KeyboardInterrupt: User presses Ctrl+C.

Best Practices:

Following are the best practices one need to follow while handling exception in program:

  • Specific Exception Handling: Use specific except blocks to handle different exception types and provide tailored responses.
  • Handle Common Exceptions: Anticipate potential errors and include appropriate exceptions blocks.
  • Don't Overuse except: Be mindful not to catch too many exceptions, as it can mask unexpected issues.
  • Log Exceptions: Consider using logging or alternative methods to record exception details for debugging and analysis.
  • Provide Informative Error Messages: Offer meaningful messages to users or administrators except blocks.
  • Test Thoroughly: Write comprehensive unit tests to cover various code paths and exception scenarios.

Key Concepts in Python Exception Handling:

1. try block:

  • Marks the code you expect might raise exceptions.

Example:

value = input("Enter a number: ")
try:
    number = int(value)
except ValueError:
    print("Invalid input: Please enter a number.")

Output:

Enter a number: aa
Invalid input: Please enter a number.

Explanation: The try block attempts to convert the user's input (value) to an integer (number).

2. except block:

  • Handles specific exceptions raised within the try block.
  • You can have multiple except blocks for different exceptions.

Example :

value = input("Enter a number: ")
try:
    number = int(value)
except ValueError:
    print("Invalid input: Please enter a number.")
except:  # General exception handler (use with caution)
    print("An unexpected error occurred.")

output:

Enter a number: abcd
Invalid input: Please enter a number.

Explanation: The first except handles ValueError for invalid input. The second except (use cautiously) catches other unexpected exceptions.

3. else block:

  • Executes only if no exceptions occur in the try block.
  • Optional, often used for code that should run when everything goes well.

Example :

value = input("Enter a number: ")
try:
    number = int(value)
except ValueError:
    print("An unexpected error occurred.")
else:
    print("You entered:", number)


Output:

Enter a number: 10
You entered: 10

Explanation: The else block prints the converted number if no exceptions occur.

4. finally block:

  • Always executes, regardless of exceptions.
  • Useful for cleanup tasks like closing resources or logging errors.

Example:

try:
    # Code that may raise an exception
    result = 10 / 0  # This will raise a ZeroDivisionError
except ZeroDivisionError:
    print("Error: Division by zero!")
finally:
    # Code that should be executed regardless of whether an exception occurred
    print("This will always execute, regardless of exceptions.")

Output:

Error: Division by zero!
This will always execute, regardless of exceptions.

Explanation: The finally block ensures cleanup happens even if there are errors.

Raising Exceptions:

  • Signal errors or invalid conditions using raise.

Example:

try:
    # Code that may raise an exception
    x = int(input("Enter a number greater than 10: "))
    if x <= 10:
        raise ValueError("Number must be greater than 10")
except ValueError as ve:
    print("Error:", ve)
finally:
    # Code that should be executed regardless of whether an exception occurred
    print("This will always execute, regardless of exceptions.")

Output:

Enter a number greater than 10: 7
Error: Number must be greater than 10
This will always execute, regardless of exceptions.