How can I "jump" into stackframe from exception?
<p>Having a raised <code>exception</code> I would like to jump into that frame. To explain better what I mean I wrote this mwe:</p>

<p>Assuming I have the following code:</p>

<pre><code>from multiprocessing import Pool
import sys

# Setup debugger
def raiseDebugger(*args):
    """ http://code.activestate.com/recipes/65287-automatically-start-the-
    debugger-on-an-exception/ """

    import traceback, pdb
    traceback.print_exception(*args)
    pdb.pm()

sys.excepthook = raiseDebugger


# Now start with the question

def faulty(i):
    return 1 / i


with Pool() as pool:
    pool.map(faulty, range(6))
</code></pre>

<p>which unsurprisingly leads to:</p>

<pre><code>multiprocessing.pool.RemoteTraceback:
"""
Traceback (most recent call last):
  File "/home/bin/conda/lib/python3.5/multiprocessing/pool.py", line 119, in worker
    result = (True, func(*args, **kwds))
  File "/home/bin/conda/lib/python3.5/multiprocessing/pool.py", line 44, in mapstar
    return list(map(*args))
  File "test2.py", line 19, in faulty
    return 1 / i
ZeroDivisionError: division by zero
"""

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

Traceback (most recent call last):
  File "test2.py", line 23, in &lt;module&gt;
    pool.map(faulty, range(6))
  File "/home/bin/conda/lib/python3.5/multiprocessing/pool.py", line 260, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "/home/bin/conda/lib/python3.5/multiprocessing/pool.py", line 608, in get
    raise self._value
ZeroDivisionError: division by zero
&gt; /home/bin/conda/lib/python3.5/multiprocessing/pool.py(608)get()
-&gt; raise self._value
(Pdb)
</code></pre>

<p>Now to debug the problem I would like to "jump" into the frame which originally raised the <code>exception</code> (<code>ZeroDivisionError</code>). </p>

<p>The original exception is still available under <code>self._value</code> complete with <code>self._value.__traceback__</code>.</p>

<p>The call that <code>pm</code> (or <code>post_mortem</code>) calls is from the value field of <a href="https://docs.python.org/3/library/sys.html#sys.exc_info" rel="nofollow"><code>sys.exc_info</code></a>, and the default invocation of <code>post_mortem</code> is done on the <code>__traceback__</code> of that value.  However if you want to get to the underlying object, you want to access its <code>__context__</code> instead.  Given this code example:</p>

<pre><code>import pdb
import sys
import traceback

def top():
    value = 1
    raise Exception('this always fails')

def bottom():
    try:
        top()
    except Exception as bot_ex:
        x = {}
        return x['nothing']

try:
    bottom()
except Exception as main_ex:
    pdb.post_mortem()
</code></pre>

<p>Running the code.  The <code>main_ex</code> would be analogous to your <code>self._value</code>.</p>

<pre><code>&gt; /tmp/foo.py(14)bottom()
-&gt; return x['nothing']
(Pdb) main_ex
KeyError('nothing',)
(Pdb) pdb.post_mortem(main_ex.__traceback__)
&gt; /tmp/foo.py(14)bottom()
-&gt; return x['nothing']
</code></pre>

<p>Note we have a new pdb prompt at the same location, which is where the exception was originally raised.  Let's try it with <code>__context__</code> if we need to go further up:</p>

<pre><code>(Pdb) c
(Pdb) pdb.post_mortem(main_ex.__context__.__traceback__)
&gt; /tmp/foo.py(7)top()
-&gt; raise Exception('this always fails')
</code></pre>

<p>If needed, keep repeating until you get to the target context/traceback desired.</p>

<hr>

<p>Now for the multiprocessing case, which I wasn't aware would have made this much difference, as the question implies something general (How can I âjumpâ into stackframe from exception?), but it turns out the specifics in <code>multiprocessing</code> made all the difference.</p>

<p>In Python 3.4 a workaround was done to just show that traceback as a string; due to how much stuff a traceback actually has, communicating all that proved to be difficult as discussed in the <a href="http://bugs.python.org/issue13831Ups" rel="nofollow">issue 13831</a> on the Python tracker, so instead a hack was done to bring a <code>__cause__</code> attribute into the current exception, but it is no full <code>__traceback__</code> as it just has the string representation of that, as I had suspected.</p>

<p>Anyway this is what would have happened:</p>

<pre><code>(Pdb) !import pdb
(Pdb) !self._value.__cause__
RemoteTraceback('\n"""\nTraceback (most recent call last):...',)
(Pdb) !type(self._value.__cause__)
&lt;class 'multiprocessing.pool.RemoteTraceback'&gt;
(Pdb) !self._value.__cause__.__traceback__
(Pdb) !self._value.__cause__.__context__
</code></pre>

<p>So this isn't actually possible until they figure out how to bring all those states across process boundaries.</p>

python python-3.x debugging exception