raise

How Python code signals failure: raise an exception object (or class), re-raise the current one with a bare raise, and record why with from.

Errors & contextPython 3 (all)Live demo
raise
raise ValueError('bad input')
re-raise
except OSError:
    log_it()
    raise
raise … from
except KeyError as e:
    raise LookupError(msg) from e
hide the context
raise TypeError(msg) from None
Use for
raise ValueError(f"...") for bad input; bare raise to pass an error on after logging
Result
a statement — never finishes normally; control jumps to the nearest matching except
Pairs with
try / except, from, custom Exception subclasses, assert
Watch out
raise needs a BaseException subclass or instance — not a string, not NotImplemented

Demo

Live evaluation
Guard a function against bad input. A negative age raises; anything else is returned.
Try:
Inputs
ageinttry -5
Code
def set_age(age):
    if age < 0:
        raise ValueError(f'age must be >= 0, got {age}')
    return age
set_age(30)
Result
30

In the raise tab the message is built with an f-string at the moment of raising — include the offending value, it is the most useful part of a traceback. In the from tab, err.__cause__ is the original IndexError object; an uncaught chained error prints both tracebacks joined by "The above exception was the direct cause of the following exception". A float index (1e21 or more) raises TypeError instead, which nothing here catches. In the bare raise tab the message the caller sees is the original one: bare raise does not create a new exception.

Syntax slots

NameTypeRequiredDescription
exceptionexpressionnoAn exception instance, or a class (instantiated with no arguments). Omitted: re-raise the exception currently being handled.
from causeexpressionnoAn exception (or class) stored as __cause__ of the new one, or None to hide the implicit __context__ from the traceback.

Common patterns

Validate arguments
ValueError for a bad value, TypeError for a bad type; put the value in the message.
def withdraw(amount):
    if amount <= 0:
        raise ValueError(f'amount must be positive, got {amount!r}')
Custom exception type
Subclass Exception so callers can catch your error specifically.
class ConfigError(Exception):
    pass

raise ConfigError('missing key: port')
Translate and chain
Wrap a library error in your own type without losing it.
try:
    data = json.loads(text)
except json.JSONDecodeError as e:
    raise ConfigError('config is not valid JSON') from e
Abstract method placeholder
The exception class, not the NotImplemented constant.
def area(self):
    raise NotImplementedError('subclasses must implement area()')

Examples

1. Raise with a message
raise ValueError('negative size')
Returns
ValueError: negative size
2. A class is instantiated for you
try: raise IndexError except IndexError as e: print(repr(e), e.args)
Returns
IndexError() ()
3. Custom exception class
class InsufficientFunds(Exception): pass raise InsufficientFunds('balance 5, need 10')
Returns
InsufficientFunds: balance 5, need 10
4. from sets __cause__
try: try: {}['id'] except KeyError as e: raise LookupError('user not found') from e except LookupError as err: print(repr(err.__cause__))
Returns
KeyError('id')
5. Raising inside except sets __context__
try: try: 1 / 0 except ZeroDivisionError: raise ValueError('while handling') except ValueError as err: print(repr(err.__context__), err.__cause__)
Returns
ZeroDivisionError('division by zero') None
6. from None hides the context
try: try: int('x') except ValueError: raise TypeError('expected a number') from None except TypeError as err: print(err.__cause__, err.__suppress_context__)
Returns
None True
7. Bare raise with nothing to re-raise
raise
Returns
RuntimeError: No active exception to reraise
8. Only exceptions can be raised
raise 'something broke'
Returns
TypeError: exceptions must derive from BaseException

Pitfalls

1. Python 2 syntax: raise E, "message"
The comma form was removed in Python 3 — call the class with the message instead.
comma form
compile("raise ValueError, 'bad'", '<demo>', 'exec')
SyntaxError: invalid syntax
call the class
raise ValueError('bad')
ValueError: bad
2. raise NotImplemented instead of NotImplementedError
NotImplemented is a constant for binary operators, not an exception. Raising it is itself an error.
the constant
raise NotImplemented
TypeError: exceptions must derive from BaseException
the exception
raise NotImplementedError('area() not written yet')
NotImplementedError: area() not written yet
3. Translating an error without from
Raising inside except only records the old error as __context__, and the traceback says "During handling of the above exception, another exception occurred" — as if your handler crashed. from e marks it as the intended cause.
implicit context
try:
    try:
        {}['port']
    except KeyError:
        raise RuntimeError('config broken')
except RuntimeError as err:
    print(err.__cause__)
None
raise … from e
try:
    try:
        {}['port']
    except KeyError as e:
        raise RuntimeError('config broken') from e
except RuntimeError as err:
    print(repr(err.__cause__))
KeyError('port')

When to use

Use it
  • A function receives input it cannot work with (ValueError, TypeError)
  • A situation the caller must deal with, where returning a special value would be ignored
  • Re-raising after logging or cleanup (bare raise)
  • Wrapping a low-level error in your own type (raise … from e)
Reach for something else
  • Internal "this cannot happen" checks during development → assert
  • Normal, expected outcomes like "not found" in a search → return None or a default
  • Stopping a generator → return (raising StopIteration inside one becomes RuntimeError)

Notes

CPython impl
raise X from Y sets X.__cause__ = Y and X.__suppress_context__ = True; __context__ is set automatically whenever an exception is raised while another is being handled
Class or instance
raise ValueError is the same as raise ValueError() — the class is called with no arguments
from
The from keyword is shared with import (from module import name) and yield from; this page covers its raise meaning

FAQ

Inside an except block both re-raise the same exception object. Bare raise is the idiom: it is shorter and needs no as name. raise e additionally adds the current line to the traceback.

History

3.3
None is permitted as the cause in raise X from None; __suppress_context__ was added.
3.11
A bare raise re-raises with the traceback as modified in the except clause, not the one it had when caught.