Raise is re-raising the last exception you caught, not the last exception you raised

(reposted from comments for clarity)

🌐
Python documentation
docs.python.org › 3 › tutorial › errors.html
8. Errors and Exceptions — Python 3.14.3 documentation
The sole argument to raise indicates the exception to be raised. This must be either an exception instance or an exception class (a class that derives from BaseException, such as Exception or one of its subclasses).
🌐
W3Schools
w3schools.com › python › ref_keyword_raise.asp
Python raise Keyword
Python Examples Python Compiler ... Interview Q&A Python Bootcamp Python Certificate Python Training ... The raise keyword is used to raise an exception....
Discussions

Explain the term “raise an exception” without using the terms “raise” or “throw”
Try reading about excepting handling in python with some example code, this should help you understand. https://www.programiz.com/python-programming/exception-handling TL;DR; sequential execution is stopped when an exception happens, and it looks for an except: block to handle it, and starts executing a matching except block. If no such block found anywhere, including above functions etc, it is finally shown as an error to the user stopping the entire code. More on reddit.com
🌐 r/learnpython
11
0
February 23, 2022
`raise` as a function - Ideas - Discussions on Python.org
In Python,raise is a keyword (used to raise exceptions). Recently I was writing some code that was using ‘boolean-operations’, like: x = a() or b() Resulting in x getting the value of b() if a() returned falsy. But b() could also return falsy, and I want to detect that and raise an error. More on discuss.python.org
🌐 discuss.python.org
1
October 17, 2025
exception - What does raise in Python raise? - Stack Overflow
Consider the following code: try: raise Exception("a") except: try: raise Exception("b") finally: raise This will raise Exception: a. I expected it to raise Exception: b ( More on stackoverflow.com
🌐 stackoverflow.com
How to use "raise" keyword in Python - Stack Overflow
I have read the official definition of "raise", but I still don't quite understand what it does. In simplest terms, what is "raise"? Example usage would help. More on stackoverflow.com
🌐 stackoverflow.com
🌐
W3Schools
w3schools.com › python › gloss_python_raise.asp
Python Raise an Exception
As a Python developer you can choose to throw an exception if a condition occurs. To throw (or raise) an exception, use the raise keyword.
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-raise-keyword
Python Raise Keyword - GeeksforGeeks
July 23, 2025 - Python raise Keyword is used to raise exceptions or errors. The raise keyword raises an error and stops the control flow of the program.
🌐
Reddit
reddit.com › r/learnpython › explain the term “raise an exception” without using the terms “raise” or “throw”
r/learnpython on Reddit: Explain the term “raise an exception” without using the terms “raise” or “throw”
February 23, 2022 -

I’m a python learner and am pretty ok with the syntax, and am now finding myself struggling with some of the deeper concepts, in this case error handling. Our environment is python running in a pytest framework using some pre-structured functions along with scripts and functions we write ourselves. I have visibility into the scripts and functions I write, along with some of the pre-structured functions, but the lowest level functions are beyond my view and control. I regularly run into exceptions in these lower levels and am trying to understand what’s going on. All the references I find say something like “raising an exception is when an executions error occurs, the error is raised as an exception”. This makes me nuts as they are explaining the term by using the term. So… Q1: what happens when an “exception is raised”? In terms of program execution and control and variables. Q2: if my script calls a function1 that calls a function2 which contains a command that “raises an exception” can I catch and handle it in function1 or in my top-level script, and if so, how? Q3: if I’m asking the wrong question, what should I be asking and/or researching?

Top answer
1 of 5
4
Try reading about excepting handling in python with some example code, this should help you understand. https://www.programiz.com/python-programming/exception-handling TL;DR; sequential execution is stopped when an exception happens, and it looks for an except: block to handle it, and starts executing a matching except block. If no such block found anywhere, including above functions etc, it is finally shown as an error to the user stopping the entire code.
2 of 5
4
So… Q1: what happens when an “exception is raised”? Go back a step - what happens when a function is called? Maybe you've got an idea, but let's be explicit - what happens is that the interpreter "puts a pin" in what it's currently doing, the line it's currently executing, and it jumps to the body of the function and executes that. Only it's not actually a pin, it's a stack frame. It puts a frame on the call stack - a collection of these frames, in the form of a stack, that the interpreter is using to keep track of where it needs to go back to when the function returns - and starts executing the body of the function that was called. If that function calls a function, then another frame goes on the call stack and you jump into the body of the new function. When the function returns, you "pop" a frame off the stack, and you return to where the function was called, possibly holding a return value. If you've written functions that call functions (that call functions, etc...) then you've had some intuitive notion of "returning" all the way back to where you started. That's called "unwinding the stack." When you raise an exception, somewhere deep in a nest of called functions, what the interpreter does is start removing stack frames from the stack, immediately returning functions wherever they're currently at in their execution. It keeps track as it does so, and you see that in the error output as something called the exception stacktrace: Traceback (most recent call last): File "/path/to/example.py", line 4, in greet('Chad') File "/path/to/example.py", line 2, in greet print('Hello, ' + someon) NameError: name 'someon' is not defined The interpreter pops stack frames until one of two things happens - either you pop all the way to an empty stack and your Python program exits with a relevant error code, or you pop into the body of a try block. If the try block is followed by an except block that declares it can handle errors of that type (so, except NameError to catch our example exception above) then the interpreter stops popping stack frames and moves execution to that except block and continues from there. That's what it means to raise an exception - it means "start to unwind the execution call stack of your program until the interpreter finds itself in a frame where the exception can be handled, or it runs out of frames."
🌐
Real Python
realpython.com › ref › keywords › raise
raise | Python Keywords – Real Python
In Python, the raise keyword allows you to trigger exceptions manually.
🌐
Python.org
discuss.python.org › ideas
`raise` as a function - Ideas - Discussions on Python.org
October 17, 2025 - In Python,raise is a keyword (used to raise exceptions). Recently I was writing some code that was using ‘boolean-operations’, like: x = a() or b() Resulting in x getting the value of b() if a() returned falsy. But b…
Find elsewhere
🌐
Python
docs.python.org › 3 › library › exceptions.html
Built-in Exceptions — Python 3.14.3 documentation
Raised when the interpreter finds an internal error, but the situation does not look so serious to cause it to abandon all hope. The associated value is a string indicating what went wrong (in low-level terms). In CPython, this could be raised by incorrectly using Python’s C API, such as returning a NULL value without an exception set.
🌐
Sentry
sentry.io › sentry answers › python › raise an exception in python
Raise an exception in Python | Sentry
June 15, 2023 - Python provides a large number of default exceptions arranged in a class hierarchy from least to most specific. When catching exceptions, all subclasses will be caught by except clauses using their parents. Therefore, the topmost class Exception is likely to be missed in favor of an exception that uses one of its subclasses. Consider the code below: def divide_by_zero(): return 1 / 0 # will fail and raise a ZeroDivisionError try: divide_by_zero() raise Exception("My custom exception.") except Exception as e: print(f"Caught error: {repr(e)}")
🌐
Python Morsels
pythonmorsels.com › how-to-throw-an-exception
How to raise an exception in Python - Python Morsels
January 17, 2022 - If you have a specific condition in your function that should loudly crash your program (if/when that condition is met) you can raise an exception (a.k.a. "throw an exception") by using the raise statement and providing an exception object to raise. You can make an exception object by calling an exception class, passing in a helpful error message. ... Python Jumpstart is designed to help new Python programmers get up to speed quickly.
🌐
Python
peps.python.org › pep-3109
PEP 3109 – Raising Exceptions in Python 3000 | peps.python.org
Because of its relation to exception raising, the signature for the throw() method on generator objects will change, dropping the optional second and third parameters. The signature thus changes (PEP 342) from ... Where EXCEPTION is either a subclass of BaseException or an instance of a subclass of BaseException. In Python 2, the following raise statement is legal
🌐
Real Python
realpython.com › python-raise-exception
Python's raise: Effectively Raising Exceptions in Your Code – Real Python
January 25, 2025 - In this tutorial, you'll learn how to raise exceptions in Python, which will improve your ability to efficiently handle errors and exceptional situations in your code. This way, you'll write more reliable, robust, and maintainable code.
Top answer
1 of 4
554

The difference is that when you use from, the __cause__ attribute is set and the message states that the exception was directly caused by. If you omit the from then no __cause__ is set, but the __context__ attribute may be set as well, and the traceback then shows the context as during handling something else happened.

Setting the __context__ happens if you used raise in an exception handler; if you used raise anywhere else no __context__ is set either.

If a __cause__ is set, a __suppress_context__ = True flag is also set on the exception; when __suppress_context__ is set to True, the __context__ is ignored when printing a traceback.

When raising from a exception handler where you don't want to show the context (don't want a during handling another exception happened message), then use raise ... from None to set __suppress_context__ to True.

In other words, Python sets a context on exceptions so you can introspect where an exception was raised, letting you see if another exception was replaced by it. You can also add a cause to an exception, making the traceback explicit about the other exception (use different wording), and the context is ignored (but can still be introspected when debugging). Using raise ... from None lets you suppress the context being printed.

See the raise statement documenation:

The from clause is used for exception chaining: if given, the second expression must be another exception class or instance, which will then be attached to the raised exception as the __cause__ attribute (which is writable). If the raised exception is not handled, both exceptions will be printed:

>>> try:
...     print(1 / 0)
... except Exception as exc:
...     raise RuntimeError("Something bad happened") from exc
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

A similar mechanism works implicitly if an exception is raised inside an exception handler or a finally clause: the previous exception is then attached as the new exception’s __context__ attribute:

>>> try:
...     print(1 / 0)
... except:
...     raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

Also see the Built-in Exceptions documentation for details on the context and cause information attached to exceptions.

2 of 4
25

In 2005, PEP 3134, Exception Chaining and Embedded Tracebacks introduced exception chaining:

  • implicit chaining with explicit raise EXCEPTION or implicit raise (__context__ attribute);
  • explicit chaining with explicit raise EXCEPTION from CAUSE (__cause__ attribute).

Motivation

During the handling of one exception (exception A), it is possible that another exception (exception B) may occur. In today’s Python (version 2.4), if this happens, exception B is propagated outward and exception A is lost. In order to debug the problem, it is useful to know about both exceptions. The __context__ attribute retains this information automatically.

Sometimes it can be useful for an exception handler to intentionally re-raise an exception, either to provide extra information or to translate an exception to another type. The __cause__ attribute provides an explicit way to record the direct cause of an exception.

[…]

Implicit Exception Chaining

Here is an example to illustrate the __context__ attribute:

def compute(a, b):
    try:
        a/b
    except Exception, exc:
        log(exc)

def log(exc):
    file = open('logfile.txt')  # oops, forgot the 'w'
    print >>file, exc
    file.close()

Calling compute(0, 0) causes a ZeroDivisionError. The compute() function catches this exception and calls log(exc), but the log() function also raises an exception when it tries to write to a file that wasn’t opened for writing.

In today’s Python, the caller of compute() gets thrown an IOError. The ZeroDivisionError is lost. With the proposed change, the instance of IOError has an additional __context__ attribute that retains the ZeroDivisionError.

[…]

Explicit Exception Chaining

The __cause__ attribute on exception objects is always initialized to None. It is set by a new form of the raise statement:

raise EXCEPTION from CAUSE

which is equivalent to:

exc = EXCEPTION
exc.__cause__ = CAUSE
raise exc

In the following example, a database provides implementations for a few different kinds of storage, with file storage as one kind. The database designer wants errors to propagate as DatabaseError objects so that the client doesn’t have to be aware of the storage-specific details, but doesn’t want to lose the underlying error information.

class DatabaseError(Exception):
    pass

class FileDatabase(Database):
    def __init__(self, filename):
        try:
            self.file = open(filename)
        except IOError, exc:
            raise DatabaseError('failed to open') from exc

If the call to open() raises an exception, the problem will be reported as a DatabaseError, with a __cause__ attribute that reveals the IOError as the original cause.

Enhanced Reporting

The default exception handler will be modified to report chained exceptions. The chain of exceptions is traversed by following the __cause__ and __context__ attributes, with __cause__ taking priority. In keeping with the chronological order of tracebacks, the most recently raised exception is displayed last; that is, the display begins with the description of the innermost exception and backs up the chain to the outermost exception. The tracebacks are formatted as usual, with one of the lines:

The above exception was the direct cause of the following exception:

or

During handling of the above exception, another exception occurred:

between tracebacks, depending whether they are linked by __cause__ or __context__ respectively. Here is a sketch of the procedure:

def print_chain(exc):
    if exc.__cause__:
        print_chain(exc.__cause__)
        print '\nThe above exception was the direct cause...'
    elif exc.__context__:
        print_chain(exc.__context__)
        print '\nDuring handling of the above exception, ...'
    print_exc(exc)

[…]

In 2012, PEP 415, Implement Context Suppression with Exception Attributes introduced exception context suppression with explicit raise EXCEPTION from None (__suppress_context__ attribute).

Proposal

A new attribute on BaseException, __suppress_context__, will be introduced. Whenever __cause__ is set, __suppress_context__ will be set to True. In particular, raise exc from cause syntax will set exc.__suppress_context__ to True. Exception printing code will check for that attribute to determine whether context and cause will be printed. __cause__ will return to its original purpose and values.

There is precedence for __suppress_context__ with the print_line_and_file exception attribute.

To summarize, raise exc from cause will be equivalent to:

exc.__cause__ = cause
raise exc

where exc.__cause__ = cause implicitly sets exc.__suppress_context__.

So in PEP 415, the sketch of the procedure given in PEP 3134 for the default exception handler (its job is to report exceptions) becomes the following:

def print_chain(exc):
    if exc.__cause__:
        print_chain(exc.__cause__)
        print '\nThe above exception was the direct cause...'
    elif exc.__context__ and not exc.__suppress_context__:
        print_chain(exc.__context__)
        print '\nDuring handling of the above exception, ...'
    print_exc(exc)
🌐
Composingprograms
composingprograms.com › pages › 33-exceptions.html
3.3 Exceptions
The Python interpreter raises an exception each time it detects an error in an expression or statement.
🌐
Coursera
coursera.org › tutorials › python-exception
How to Catch, Raise, and Print a Python Exception | Coursera
Additionally, handling exceptions this way enables you to replace the interpreter’s error message with a much more user friendly one. The raise statement allows you to force an error to occur.
🌐
Tutorialspoint
tutorialspoint.com › python › python_raising_exceptions.htm
Python - Raising Exceptions
To re-raise an exception in Python, you use the "raise" statement without specifying an exception, which will re-raise the last exception that was active in the current scope.
🌐
Real Python
realpython.com › python-exceptions
Python Exceptions: An Introduction – Real Python
December 1, 2024 - Python exceptions provide a mechanism for handling errors that occur during the execution of a program. Unlike syntax errors, which are detected by the parser, Python raises exceptions when an error occurs in syntactically correct code.