Python raise Statement

In the last lesson, we learned about Python finally Block. Now let’s raise exceptions when our own rules are broken.

Let’s Talk About Creating Our Own Errors

We know about exceptions. They happen when something goes wrong. Like dividing by zero. Or accessing a missing key. Python raises those exceptions automatically.

But sometimes, we want to raise an exception ourselves. Because we know something is wrong. And we want to stop the program or signal an error.

That is what the raise statement is for.

What Is raise in Python?

raise is a keyword that lets us throw an exception on purpose.

We use it when we detect a problem that Python would not catch on its own. For example, if someone passes a negative number to a function that only accepts positive numbers. Python does not know that rule. But we do. So we raise an exception.

Think of it like this. We are a referee in a game. If a player breaks a rule, we blow the whistle. We stop the game. raise is our whistle.

How to Raise an Exception in Python

We write raise followed by the exception we want to raise.

raise ValueError("This is a custom error message")

When this line runs, Python raises a ValueError with that message. And the program stops, unless the exception is caught.

Let’s see a full example.

age = -5
if age < 0:
raise ValueError("Age cannot be negative")
print(f"Age is {age}")

Output

Traceback (most recent call last):
File "example.py", line 4, in <module>
raise ValueError("Age cannot be negative")
ValueError: Age cannot be negative

The program crashes with our custom message. That is what we wanted.

Raising Built-In Exceptions in Python

We can raise any of Python’s built-in exceptions. Here are some common ones.

  • ValueError — when a value is not valid
  • TypeError — when a type is wrong
  • IndexError — when an index is out of range
  • KeyError — when a key is missing
  • ZeroDivisionError — when dividing by zero
  • NotImplementedError — when a method is not implemented yet
def divide(a, b):
if b == 0:
raise ZeroDivisionError("Cannot divide by zero")
return a / b

That is the same as what Python would do. But sometimes we want a custom message.

Raising an Exception Without a Message

We can raise an exception without a message.

raise ValueError

That works. But it is less helpful. The error message will be empty. So it is better to include a message.

Raising an Exception with a Custom Message in Python

The message is just a string. It can be anything.

def set_age(age):
if age < 0:
raise ValueError("Age cannot be negative. You entered: " + str(age))
if age > 150:
raise ValueError("Age seems too high. You entered: " + str(age))
return age

Now if we call set_age(-5), we get a clear error message.

Re-raising an Exception in Python

Sometimes we catch an exception, do something, and then want to raise it again. We can use raise without any arguments.

try:
number = int(input("Enter a number: "))
except ValueError:
print("That was not a number")
raise

Output

Enter a number: hello
That was not a number
Traceback (most recent call last):
File "example.py", line 2, in <module>
number = int(input("Enter a number: "))
ValueError: invalid literal for int() with base 10: 'hello'

The raise inside the except block re-raises the same exception. So the program still crashes, but we had a chance to log or print something first.

That is useful when we want to add context but still let the error propagate.

Raising a Different Exception in Python

We can also catch one exception and raise a different one.

try:
number = int(input("Enter a number: "))
except ValueError:
raise TypeError("Expected a number, got something else")

Now the original ValueError is replaced by a TypeError. That can be useful when we want to signal a different kind of problem.

But let’s be careful. We lose the original traceback. In Python 3, we can use raise ... from ... to keep the chain.

try:
number = int(input("Enter a number: "))
except ValueError as e:
raise TypeError("Expected a number") from e

That shows both exceptions in the traceback. It is more informative.

Python raise Statement: A Real-Life Example

Let’s build a function that calculates the square root of a number. But it only works for non-negative numbers.

import math
def safe_sqrt(x):
if x < 0:
raise ValueError("Cannot take square root of a negative number")
return math.sqrt(x)

Now if we call safe_sqrt(-4), we get:

ValueError: Cannot take square root of a negative number

If we call safe_sqrt(16), we get 4.0.

That is a clean way to enforce rules.

Another Example — Validating Input

def get_positive_number():
number = float(input("Enter a positive number: "))
if number <= 0:
raise ValueError("Number must be positive")
return number
try:
num = get_positive_number()
print(f"You entered: {num}")
except ValueError as e:
print(f"Error: {e}")

If the user enters -5, they see Error: Number must be positive. If they enter 10, they see You entered: 10.0.

That is a simple validation pattern.

When to Use raise in Python

Use raise when:

  • We detect an invalid state that Python would not catch.
  • We want to stop the program because something is wrong.
  • We want to signal an error to the caller.
  • We are writing a library and need to enforce rules.

Let’s not use raise for normal flow control. Exceptions should be for exceptional situations.

Common Mistakes with Python raise Statement

Mistake 1: Raising a String Instead of an Exception

raise "Something went wrong" # Error!

In Python 3, we cannot raise a string. We must raise an exception class or instance.

So what do we do? We use a proper exception.

raise ValueError("Something went wrong")

Mistake 2: Raising Too Many Exceptions

Let’s not raise exceptions for every little thing. We use them when something truly unexpected or invalid happens.

Mistake 3: Forgetting to Handle the Exception

If we raise an exception, someone needs to catch it. Or the program will crash. That is fine if we want it to crash. But if we are writing a library, let’s document our exceptions so callers know what to expect.

Mistake 4: Losing the Original Exception

try:
# something
except ValueError:
raise TypeError("New error")

This loses the original ValueError. So what do we do? We use from to keep the chain.

except ValueError as e:
raise TypeError("New error") from e

Next, we will learn about Python Custom Exceptions and create error types for specific problems.