Popular Searches
Popular Course Categories
Popular Courses

Introduction to Errors and Exceptions in Python

Introduction to Errors and Exceptions in Python

Exception Handling and Debugging

Introduction to Errors and Exceptions in Python

Course: Python Training

Topic: Introduction to Errors and Exceptions in Python

Course Link: Python Training Course

Demo Link: Register for a Course Demo

Website: JustAcademy


1. Introduction

Errors and exceptions are important concepts in Python programming. They help developers identify problems in source code, understand unexpected program behavior, and build applications that handle failures gracefully.

An error may occur because of incorrect syntax, invalid operations, missing resources, unexpected input, or violations of application rules. Understanding these problems helps programmers write reliable, maintainable, and user-friendly applications.

Python provides several mechanisms for handling exceptions, including try, except, else, finally, and raise. These mechanisms allow a program to respond to expected failures instead of terminating unexpectedly.

For example, a calculator should handle division by zero, a registration form should validate user input, and a file-processing application should respond appropriately when a file cannot be opened.

2. Learning Objectives

  • Understand the meaning of errors and exceptions in Python.
  • Differentiate syntax errors, runtime errors, and logical errors.
  • Identify common built-in Python exceptions.
  • Understand how Python reports errors using tracebacks.
  • Handle exceptions using try and except.
  • Use multiple exception handlers effectively.
  • Understand the purpose of else and finally.
  • Raise exceptions using the raise statement.
  • Apply error-handling techniques in practical programs.

3. What Is an Error in Python?

An error is a problem that prevents a program from behaving as intended. Depending on the situation, Python may reject the code before execution, raise an exception during execution, or execute the code successfully while producing an incorrect result.

Example

number = 10
divisor = 0

result = number / divisor
print(result)

Result: Python raises a ZeroDivisionError because a number cannot be divided by zero.

Errors can arise from several sources, including:

  • Incorrect Python syntax.
  • Invalid data types or values.
  • Missing variables or functions.
  • Invalid mathematical operations.
  • Missing files or unavailable resources.
  • Incorrect business logic.

4. Types of Errors in Python

Python programming problems are commonly classified into syntax errors, runtime exceptions, and logical errors. These categories describe different ways a program can fail or produce incorrect results.

4.1 Syntax Errors

A syntax error occurs when Python cannot parse code because it violates the language's grammar. The program cannot execute normally until the syntax problem is corrected.

Example:

if 10 > 5
    print("Ten is greater")

Error:

SyntaxError: expected ':'

The problem is the missing colon after the condition.

Correct code:

if 10 > 5:
    print("Ten is greater")

Output:

Ten is greater

4.2 Runtime Errors and Exceptions

A runtime exception occurs when Python encounters a problem while executing a statement. The statement may be syntactically correct but impossible to complete under the current conditions.

Example:

number = 10
divisor = 0

print(number / divisor)

Error:

ZeroDivisionError: division by zero

The code follows valid Python syntax, but the division operation is invalid.

4.3 Logical Errors

A logical error occurs when a program runs without necessarily raising an exception but produces an incorrect result because the algorithm or calculation is wrong.

Example:

length = 10
width = 5

area = length + width
print("Area:", area)

Output:

Area: 15

The program executes successfully, but the formula for the area of a rectangle should multiply the length by the width.

Correct code:

length = 10
width = 5

area = length * width
print("Area:", area)

Output:

Area: 50

Comparison of Error Types

Error Type When It Occurs Example How to Fix It
Syntax error When Python cannot parse the code. Missing colon after an if statement. Correct the syntax.
Runtime exception When an operation fails during execution. Dividing by zero. Handle the exception or correct the operation.
Logical error When code runs but gives an incorrect result. Adding dimensions instead of multiplying them. Correct the algorithm or formula.

5. What Is an Exception?

An exception is an object that represents an abnormal condition encountered during program execution. Python raises an exception when an operation cannot proceed normally.

Examples include:

  • Dividing a number by zero.
  • Converting invalid text into an integer.
  • Accessing a variable that has not been defined.
  • Opening a file that does not exist.
  • Accessing an invalid list index.

Example: ValueError

age = int("twenty")
print(age)

Error:

ValueError: invalid literal for int() with base 10: 'twenty'

The int() function cannot convert the text "twenty" into an integer. Because the exception is not handled, program execution stops at that point.

6. Understanding Common Built-in Exceptions

Python includes many built-in exception classes. Each class represents a particular category of failure, allowing developers to handle different problems appropriately.

Exception Description Example
SyntaxError Invalid Python syntax. if True print("Hi")
IndentationError Incorrect indentation. An improperly indented statement.
NameError A name is not defined in the current scope. print(username) when the name is undefined.
TypeError An operation or function receives an inappropriate type. "Age: " + 20
ValueError A value has an inappropriate format or content. int("hello")
ZeroDivisionError A division or modulo operation uses zero as its divisor. 10 / 0
IndexError A sequence index is out of range. [1, 2][5]
KeyError A dictionary key does not exist. {"name": "Riya"}["age"]
AttributeError An object does not provide the requested attribute. Calling a nonexistent method.
FileNotFoundError A requested file cannot be found. Opening a missing file.
ImportError An import operation fails. Importing an unavailable name.
ModuleNotFoundError A requested module cannot be found. Importing a module that is not installed or available.
OverflowError A numeric operation exceeds a supported range for that operation. Some floating-point or mathematical operations.

7. Understanding Python Tracebacks

A traceback is the diagnostic information Python displays when an exception is not handled. It usually shows the sequence of calls that led to the error, source file names, line numbers, and the exception type and message.

Example

def calculate():
    number = 10
    divisor = 0
    return number / divisor

calculate()

Typical final traceback line:

ZeroDivisionError: division by zero

When reading a traceback, focus on the following details:

  • Exception type: Identifies the category of problem.
  • Error message: Explains the immediate failure.
  • File and line number: Identifies where the exception occurred.
  • Function call sequence: Shows how execution reached the failing statement.

Tracebacks are particularly useful when debugging applications with several functions or modules.

8. Introduction to Exception Handling

Exception handling allows a program to respond to errors without necessarily terminating immediately. Python uses a try block to identify statements that may fail and an except block to handle specified exceptions.

Basic Syntax

try:
    # Code that may raise an exception
    statement
except ExceptionType:
    # Handle the specified exception
    recovery_statement

Example: Handling Division by Zero

try:
    number = 10
    divisor = 0
    result = number / divisor
    print(result)
except ZeroDivisionError:
    print("Cannot divide by zero.")

Output:

Cannot divide by zero.

When a ZeroDivisionError occurs, Python skips the remaining statements in the try block and executes the matching except block.

9. Using Multiple Except Blocks

A program may encounter different types of exceptions. Multiple except blocks allow it to respond differently depending on which exception occurs.

Example

try:
    number = int(input("Enter a number: "))
    result = 100 / number
    print("Result:", result)
except ValueError:
    print("Please enter a valid integer.")
except ZeroDivisionError:
    print("The number cannot be zero.")

Possible outputs:

Enter a number: abc
Please enter a valid integer.

Or:

Enter a number: 0
The number cannot be zero.

Only the matching handler executes for an exception raised within the protected try block. Handling specific exceptions makes the program easier to understand and maintain.

10. Capturing Exception Messages

You can capture an exception object using as in an except clause. This allows the program to display, log, or inspect the exception message.

Example

try:
    result = 10 / 0
except ZeroDivisionError as error:
    print("An error occurred:", error)

Output:

An error occurred: division by zero

Using the exception object can provide useful diagnostic information. In production applications, avoid exposing sensitive internal details to end users; detailed diagnostics should generally be recorded in appropriate logs.

11. Using the else Clause

The else clause executes only when the try block completes without raising an exception handled by its associated handlers.

Example

try:
    number = int("25")
except ValueError:
    print("Invalid number.")
else:
    print("Conversion successful.")
    print("Number:", number)

Output:

Conversion successful.
Number: 25

The else clause keeps successful-operation code separate from the statements that need exception handling. This reduces the risk of accidentally catching errors from unrelated operations.

12. Using the finally Clause

The finally clause runs when control leaves the associated try statement, whether an exception occurred or not. It is commonly used for cleanup tasks such as releasing resources.

Example

try:
    number = 10
    divisor = 0
    print(number / divisor)
except ZeroDivisionError:
    print("Division error occurred.")
finally:
    print("Execution of the try statement is complete.")

Output:

Division error occurred.
Execution of the try statement is complete.

The finally block executes even though the division operation raises an exception.

Important: Avoid returning from a finally block because doing so can suppress an exception or override an earlier return value. For file handling, Python's with statement is often the preferred way to manage resource cleanup.

13. Using try, except, else, and finally Together

These clauses can be combined to provide a complete exception-handling structure.

Example

try:
    number = int(input("Enter a number: "))
    result = 100 / number
except ValueError:
    print("Invalid input. Enter an integer.")
except ZeroDivisionError:
    print("Zero is not allowed.")
else:
    print("Calculation successful.")
    print("Result:", result)
finally:
    print("Program operation completed.")

Example output for input 20:

Enter a number: 20
Calculation successful.
Result: 5.0
Program operation completed.

Purpose of each clause:

Clause Purpose
try Contains statements that may raise exceptions.
except Handles matching exceptions.
else Runs when the try block succeeds without an exception.
finally Runs during normal exit from the construct, including when an exception occurs.

14. Raising Exceptions Manually

The raise statement allows developers to signal an exception when a condition violates the requirements of an operation.

Example: Validating Age

age = -5

if age < 0:
    raise ValueError("Age cannot be negative")

print("Age:", age)

Result: Python raises ValueError with the message Age cannot be negative.

Raising an exception is useful when a function detects invalid input or cannot safely continue. The exception can be handled by the function's caller when appropriate.

15. Re-Raising an Exception

Sometimes a program needs to perform an action when an exception occurs but still allow the original exception to propagate. The raise statement without an argument re-raises the currently handled exception.

Example

try:
    number = int("hello")
except ValueError:
    print("Logging invalid input.")
    raise

The program prints the logging message and then re-raises the original ValueError. If no outer handler catches it, the exception remains unhandled.

This technique is useful when a function needs to record or add context to a failure without pretending that the operation succeeded.

16. Exception Hierarchy in Python

Python exceptions are organized into an inheritance hierarchy. At the top is BaseException, from which the main Exception class and several special termination-related exceptions derive.

Most application errors inherit from Exception. Exceptions such as KeyboardInterrupt and SystemExit are not subclasses of Exception, so they are not normally caught by an except Exception handler.

Simplified Hierarchy

BaseException
|
+-- Exception
|   |
|   +-- ArithmeticError
|   |   +-- ZeroDivisionError
|   |   +-- OverflowError
|   |
|   +-- LookupError
|   |   +-- IndexError
|   |   +-- KeyError
|   |
|   +-- TypeError
|   +-- ValueError
|   +-- OSError
|       +-- FileNotFoundError
|
+-- KeyboardInterrupt
+-- SystemExit

This is a simplified illustration, not a complete list of Python's exception classes. Understanding inheritance helps developers choose appropriate handlers and create custom exception hierarchies.

17. Catching Multiple Exception Types Together

When several exception types require the same response, they can be grouped in a tuple inside an except clause.

Example

try:
    value = int(input("Enter a number: "))
    result = 100 / value
except (ValueError, ZeroDivisionError) as error:
    print("Input or calculation error:", error)

This approach reduces repeated code when multiple exceptions can be handled in the same way. Use separate handlers when different exceptions require different recovery actions.

18. Exception Chaining

Exception chaining preserves the relationship between an original exception and a new exception raised while handling it. This is useful when translating a low-level failure into a more meaningful application-level error.

Example

def load_age(text):
    try:
        return int(text)
    except ValueError as error:
        raise RuntimeError("Unable to process the age value") from error

try:
    load_age("unknown")
except RuntimeError as error:
    print("Application error:", error)
    print("Original cause:", error.__cause__)

Output:

Application error: Unable to process the age value
Original cause: invalid literal for int() with base 10: 'unknown'

The from error expression explicitly records the original exception as the cause of the new exception. This helps preserve useful diagnostic information.

19. Common Mistakes in Exception Handling

Mistake 1: Using a Bare Except Clause Everywhere

try:
    result = 10 / 0
except:
    print("Something went wrong.")

A bare except catches exceptions beyond ordinary application errors, including some termination-related exceptions. Prefer catching specific exception types when possible.

Mistake 2: Catching Exception Without a Clear Reason

try:
    number = int("hello")
except Exception:
    print("Error")

This may hide the distinction between different failures. Use except ValueError when invalid conversion is the expected failure.

Mistake 3: Ignoring Exceptions

try:
    result = 10 / 0
except ZeroDivisionError:
    pass

Silently ignoring an exception can make a program appear successful even when an operation has failed. Only suppress an exception when the failure is genuinely safe to ignore.

Mistake 4: Placing Too Much Code Inside try

A large try block may catch exceptions from statements unrelated to the operation being protected. Keep the protected section focused on the statements that may reasonably raise the exceptions you intend to handle.

Mistake 5: Misunderstanding Logical Errors

Exception handling does not automatically detect incorrect formulas or algorithms. Logical errors still require testing, debugging, validation, and careful review of the program's requirements.

20. Best Practices for Error and Exception Handling

  • Understand the cause of an error before attempting to fix it.
  • Read the traceback carefully, especially the final exception line and relevant source locations.
  • Catch specific exceptions whenever possible.
  • Use else to separate successful processing from exception handling.
  • Use finally for cleanup when appropriate.
  • Use with for resources such as files that support context management.
  • Validate user input before performing sensitive calculations or operations.
  • Raise appropriate exceptions when a function cannot satisfy its contract.
  • Preserve the original cause when converting exceptions.
  • Avoid silently ignoring unexpected failures.
  • Record useful diagnostic information without exposing secrets or sensitive data.
  • Test both successful and failing execution paths.

21. Practical Example: Student Marks Validation

This example demonstrates how to handle invalid numeric input and validate marks before calculating a result.

def calculate_result(marks):
    if marks < 0 or marks > 100:
        raise ValueError("Marks must be between 0 and 100")

    if marks >= 40:
        return "Pass"

    return "Fail"

try:
    marks = int(input("Enter student marks: "))
    result = calculate_result(marks)
except ValueError as error:
    print("Invalid marks:", error)
else:
    print("Student result:", result)
finally:
    print("Result processing completed.")

Example output for input 85:

Enter student marks: 85
Student result: Pass
Result processing completed.

Example output for input 120:

Enter student marks: 120
Invalid marks: Marks must be between 0 and 100
Result processing completed.

The same ValueError handler covers both invalid integer conversion and invalid marks. In a larger application, separate validation exception classes may be appropriate if these situations need different responses.

22. Practical Example: Safe File Handling

Files may be unavailable because they do not exist, access is denied, or an operating system operation fails. Exception handling allows the program to respond to these conditions.

try:
    with open("student_data.txt", "r", encoding="utf-8") as file:
        content = file.read()
except FileNotFoundError:
    print("The requested file does not exist.")
except PermissionError:
    print("Permission denied while opening the file.")
except OSError as error:
    print("File operation failed:", error)
else:
    print("File contents:")
    print(content)

The with statement manages the file's lifecycle and ensures that it is closed when control leaves the block. The exception handlers address common file access failures without treating all errors as identical.

23. Mini Project: Simple Calculator with Exception Handling

Objective: Build a calculator that accepts two numbers and an arithmetic operator while handling invalid input and division by zero.

Requirements

  • Accept two numeric inputs.
  • Support addition, subtraction, multiplication, and division.
  • Handle non-numeric input.
  • Handle division by zero.
  • Display a meaningful message for unsupported operators.
  • Use else to display a successful result.

Sample Implementation

def calculator(first, second, operator):
    if operator == "+":
        return first + second
    elif operator == "-":
        return first - second
    elif operator == "*":
        return first * second
    elif operator == "/":
        if second == 0:
            raise ZeroDivisionError("Cannot divide by zero")
        return first / second
    else:
        raise ValueError("Unsupported operator")

try:
    first = float(input("Enter first number: "))
    second = float(input("Enter second number: "))
    operator = input("Enter operator (+, -, *, /): ")

    result = calculator(first, second, operator)
except ValueError as error:
    print("Input error:", error)
except ZeroDivisionError as error:
    print("Calculation error:", error)
else:
    print("Result:", result)
finally:
    print("Calculator operation completed.")

Example output:

Enter first number: 10
Enter second number: 0
Enter operator (+, -, *, /): /
Calculation error: Cannot divide by zero
Calculator operation completed.

Project extension: Add a calculation history, support exponentiation, and write unit tests for valid calculations and each error condition.

24. Practice Exercises

Exercise 1: Safe Integer Conversion

Write a program that converts a user-provided string into an integer and handles invalid input using ValueError.

Exercise 2: Division Calculator

Accept two numbers and perform division. Display a suitable message when the divisor is zero.

Exercise 3: List Index Validation

Create a list of five items and ask the user for an index. Handle invalid indexes using IndexError.

Exercise 4: Dictionary Lookup

Create a dictionary containing student names and marks. Handle missing keys using KeyError.

Exercise 5: File Reader

Open a text file and display its contents. Handle a missing file and other relevant file access errors.

Exercise 6: Age Validation

Create a function that accepts an age and raises ValueError when the age is negative.

Exercise 7: Exception Cleanup

Write a program that uses try, except, else, and finally to demonstrate successful and unsuccessful operations.

25. Interview Questions and Answers

Q1. What is an error in Python?

Answer: An error is a problem that prevents code from executing correctly or producing its intended result. It may be caused by invalid syntax, a runtime exception, or incorrect logic.

Q2. What is an exception?

Answer: An exception is an object raised to represent a problem encountered during program execution.

Q3. What is the difference between a syntax error and an exception?

Answer: A syntax error prevents Python from parsing the code, while an exception occurs when an operation fails during execution.

Q4. What is a logical error?

Answer: A logical error occurs when a program runs but produces an incorrect result because its algorithm or formula is wrong.

Q5. What is the purpose of try and except?

Answer: The try block contains code that may raise an exception, and the except block handles a matching exception.

Q6. What is the purpose of finally?

Answer: The finally block executes when control leaves the associated exception-handling construct and is commonly used for cleanup.

Q7. When does the else clause execute?

Answer: It executes when the try block completes without raising an exception.

Q8. What does the raise statement do?

Answer: It explicitly raises an exception to signal that an operation cannot continue normally.

Q9. What is a traceback?

Answer: A traceback provides diagnostic information about the call sequence and source locations associated with an exception.

Q10. What is the difference between TypeError and ValueError?

Answer: A TypeError generally indicates an inappropriate type for an operation, while a ValueError indicates that a value is inappropriate for an operation even though its type may be acceptable.

Q11. Why should specific exceptions be caught?

Answer: Specific handlers make failures easier to diagnose and reduce the risk of hiding unrelated errors.

Q12. What is exception chaining?

Answer: Exception chaining preserves the relationship between an original exception and another exception raised while handling it.

Q13. What is the purpose of the with statement?

Answer: The with statement manages resources through a context manager and supports reliable cleanup, such as closing files.

Q14. Can logical errors be handled automatically with try and except?

Answer: No. Logical errors often do not raise exceptions. They must be identified through testing, debugging, validation, and reviewing the algorithm.

26. Quick Revision Notes

  • Syntax errors occur when code violates Python grammar.
  • Runtime exceptions occur when operations fail during execution.
  • Logical errors produce incorrect results even when code runs.
  • Built-in exceptions include TypeError, ValueError, NameError, and ZeroDivisionError.
  • A traceback helps identify where an exception occurred.
  • try identifies statements that may fail.
  • except handles matching exceptions.
  • else runs when the try block succeeds.
  • finally supports cleanup during normal or exceptional exits.
  • raise explicitly signals an exception.
  • Specific exception handling is usually better than a bare except.
  • The with statement is useful for safe resource management.

27. Final Checklist

  • Understand the different types of programming errors.
  • Recognize common built-in exceptions.
  • Read and interpret tracebacks.
  • Use try and except correctly.
  • Apply multiple exception handlers where needed.
  • Understand the difference between else and finally.
  • Raise and re-raise exceptions appropriately.
  • Understand basic exception inheritance and chaining.
  • Practice handling errors in calculators, file readers, and validation functions.
  • Test both successful operations and expected failure conditions.

Conclusion

Errors and exceptions are fundamental to writing reliable Python programs. Understanding syntax errors, runtime exceptions, and logical errors helps developers identify the source of a problem and select the correct solution.

Python's exception-handling features make it possible to handle expected failures, validate input, protect important operations, and manage resources safely. By practicing try, except, else, finally, and raise, you can develop more robust and maintainable applications.


Learn More with JustAcademy

Explore the Python Training Course to strengthen your programming fundamentals, debugging skills, and understanding of exception handling.

Register for a Course Demo to learn more about the available training options.

Visit JustAcademy to explore additional courses and learning resources.

whatsapp