• Python
Python Fundamentals
  • Python Variables
  • Python Operators
  • Python Input-Output
  • Python Type Conversion
Python Data Types
  • Python Strings
  • Python List
  • Python Tuple
  • Python Dictionnaries
  • Python Sets
Python Flow Control
  • Python Conditions
  • Python For Loop
  • Python While Loop
  • Python Break and Continue
Python Functions
  • Python Functions
  • Python Arguments
  • Python Functions Scope
  • Python Recursion
Python Classes
  • Python Classes
  • Python Classes and Static Methods
  • Python Properties
  • Python Decorators
  • Python Error Handling

Create an Account

FREE

Join our community to access more courses.

Create Account
  • Pricing
  • Blog

On this page

Making Your Programs Robust: Understanding Errors and ExceptionsSyntax Errors vs. ExceptionsThe Basics: try and exceptCatching Specific ExceptionsMultiple except BlocksThe else BlockThe finally BlockRaising ExceptionsCommon Built-in ExceptionsUser-Defined ExceptionsSummary

Python Error Handling

Making Your Programs Robust: Understanding Errors and Exceptions

In Python, errors can happen for many reasons—maybe a file doesn't exist, a user enters the wrong input, or you try to divide by zero. If you don't handle these errors, your program will crash. Exception handling lets you deal with errors gracefully, so your program can keep running or fail in a controlled way.

Syntax Errors vs. Exceptions

There are two main types of errors in Python:

  • Syntax errors: These happen when Python can't understand your code at all. For example, if you forget a colon or a parenthesis:
# SyntaxError: invalid syntax
if True
    print("Hello!")
  • Exceptions: These happen while your program is running, even if the code is written correctly. For example, dividing by zero or trying to open a file that doesn't exist:
# ZeroDivisionError
result = 10 / 0

# FileNotFoundError
with open("missing.txt") as f:
    data = f.read()

The Basics: try and except

To handle exceptions, use a try block. You put the code that might cause an error inside try, and then use except to catch and handle the error.

try:
    number = int(input("Enter a number: "))
    print(10 / number)
except ZeroDivisionError:
    print("You can't divide by zero!")
except ValueError:
    print("That's not a valid number!")
  • If the user enters 0, it prints the message for ZeroDivisionError.
  • If the user enters something that's not a number, it prints the message for ValueError.

Catching Specific Exceptions

You can catch specific types of exceptions by naming them in the except block. This lets you handle different errors in different ways.

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

If you want to catch any exception (not recommended for most cases), you can use a plain except: block. But it's better to be specific so you don't hide bugs.

Multiple except Blocks

You can have several except blocks to handle different types of errors:

try:
    with open("data.txt") as f:
        content = f.read()
    number = int(content)
    print(100 / number)
except FileNotFoundError:
    print("File not found.")
except ValueError:
    print("File does not contain a valid number.")
except ZeroDivisionError:
    print("Number in file is zero!")

You can also catch multiple exceptions in one block:

try:
    risky()
except (TypeError, ValueError):
    print("A type or value error occurred.")

The else Block

You can add an else block after all the except blocks. The code in else runs only if no exception was raised in the try block.

try:
    n = int(input("Enter a number: "))
except ValueError:
    print("Not a number!")
else:
    print(f"You entered {n}")

The finally Block

A finally block will always run, whether or not an exception occurred. It's useful for cleanup actions, like closing files or releasing resources.

try:
    f = open("data.txt")
    # Do something with the file
except FileNotFoundError:
    print("File not found.")
finally:
    print("This runs no matter what.")
    if 'f' in locals() and not f.closed:
        f.close()

Raising Exceptions

You can raise exceptions yourself using the raise statement. This is useful if you want to signal that something went wrong in your own code.

def divide(a: float, b: float) -> float:
    if b == 0:
        raise ZeroDivisionError("Cannot divide by zero!")
    return a / b

print(divide(10, 2))  # Output: 5.0
# print(divide(10, 0))  # Raises ZeroDivisionError

Common Built-in Exceptions

Here are some exceptions you might see often:

  • ValueError: Raised when a function gets an argument of the right type but an inappropriate value.
  • TypeError: Raised when an operation is applied to an object of the wrong type.
  • ZeroDivisionError: Raised when you divide by zero.
  • FileNotFoundError: Raised when a file or directory is requested but doesn't exist.
  • IndexError: Raised when a sequence subscript is out of range.
  • KeyError: Raised when a dictionary key isn't found.
  • NameError: Raised when a variable is not defined.

User-Defined Exceptions

You can create your own exception types by defining a new class that inherits from Exception.

class MyCustomError(Exception):
    pass

def do_something(value: int) -> None:
    if value < 0:
        raise MyCustomError("Negative value not allowed!")
    print(f"Value is {value}")

do_something(5)   # Output: Value is 5
# do_something(-1) # Raises MyCustomError

Summary

  • Syntax errors stop your code from running at all; exceptions happen while your code is running.
  • Use try and except to handle exceptions and keep your program running.
  • Catch specific exceptions to handle different errors in different ways.
  • Use else for code that should run only if no error occurred.
  • Use finally for cleanup that should always happen.
  • You can raise exceptions yourself with raise.
  • You can define your own exception types by subclassing Exception.

Continue Learning

Removing Duplicates

Popular

Personalized Recommendations

Log in to get more relevant recommendations based on your reading history.