Is there a way to reraise a nested exception both without adding another nesting level and without removing all causes?

Consider the following two examples.

>>> try:
...     try:
...         raise Exception
...     except:
...         raise Exception
... except Exception as e:
...     raise Exception
...     
Traceback (most recent call last):
  File "<python-input-13>", line 3, in <module>
    raise Exception
Exception

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<python-input-13>", line 5, in <module>
    raise Exception
Exception

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<python-input-13>", line 7, in <module>
    raise Exception
Exception
>>> try:
...     try:
...         raise Exception
...     except:
...         raise Exception
... except Exception as e:
...     raise Exception from None
...     
Traceback (most recent call last):
  File "<python-input-14>", line 7, in <module>
    raise Exception from None
Exception

What I want, though, is an output like this:

Traceback (most recent call last):
  File "<python-input-13>", line 3, in <module>
    raise Exception
Exception

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<python-input-13>", line 5, in <module>
    raise Exception
Exception

None of

  • raise Exception
  • raise Exception from None
  • raise Exception from e

work.

How can I do this?

Hmm. I’m a bit lost in your example. Rather than using Exception everywhere, can you raise three different exception types please? Then it’d be clear which ones you’re expecting to be chained together.

raise E raises a new exception E.

raise on its own in an except clause re-raises the caught exception.

try:
    try:
        raise Exception
    except:
        raise Exception
except Exception as e:
    raise

In general, there’s probably a better way to structure your code. But if you need to, you can raise Exception from e.__cause__ or raise Exception from e.__context__. (The former is set by raise … from, the latter is the exception that triggered the except block where e was raised.)

>>> try:
...     try:
...         raise Exception("AAA")
...     except:
...         raise Exception("BBB")
... except:
...     raise Exception("CCC")
...     
Traceback (most recent call last):
  File "<python-input-1>", line 3, in <module>
    raise Exception("AAA")
Exception: AAA

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<python-input-1>", line 5, in <module>
    raise Exception("BBB")
Exception: BBB

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<python-input-1>", line 7, in <module>
    raise Exception("CCC")
Exception: CCC

but what I want is

Traceback (most recent call last):
  File "<python-input-1>", line 3, in <module>
    raise Exception("AAA")
Exception: AAA

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<python-input-1>", line 7, in <module>
    raise Exception("CCC")
Exception: CCC

Replace raise Exception("BBB")with just raise.

the inner try-except is standing in for some code I don’t control