When I am running inside an interactive session (in my case ipython
), and am currently inside a debugger (ipdb
or pdb
) I would like to
You can accomplish this by getting a reference to the outer interpreter's stack frame, and writing to its frame globals.
Given a sample module with a breakpoint that kicks us into pdb:
my_module.py:
def fun(arg):
import pdb; pdb.set_trace()
print arg
Example demonstrating the basic concept:
>>> import my_module
>>> my_module.fun(1)
> /Users/lukasgraf/src/stackoverflow/my_module.py(3)fun()
-> print arg
(Pdb) import sys
(Pdb) sys._getframe(0)
<frame object at 0x1032ab290>
# this is the current frame
(Pdb) sys._getframe(0).f_globals['__name__']
'my_module'
# Next outer frame
(Pdb) sys._getframe(1).f_globals['__name__']
'pdb'
# etc...
# In this example, frame 10 happens to be
# the one from the outer interpreter
(Pdb) sys._getframe(10).f_globals['__name__']
'__main__'
So here's a quick and dirty function that walks up the stack looking for '__name__'
with a value of '__main__'
in frame globals:
debughelper.py:
import sys
# Be safe and define a maximum of frames we're trying to walk up
MAX_FRAMES = 20
def save_to_interactive(dct):
n = 0
# Walk up the stack looking for '__name__'
# with a value of '__main__' in frame globals
for n in range(MAX_FRAMES):
cur_frame = sys._getframe(n)
name = cur_frame.f_globals.get('__name__')
if name == '__main__':
# Yay - we're in the stack frame of the interactive interpreter!
# So we update its frame globals with the dict containing our data
cur_frame.f_globals.update(dct)
break
Usage:
>>> import my_module
>>> my_module.fun('foo')
> /Users/lukasgraf/src/stackoverflow/my_module.py(3)fun()
-> print arg
(Pdb) import debughelper
(Pdb) debughelper.save_to_interactive({'mykey': 42})
(Pdb) c
foo
# We continued PDB, so we're in the outer interpreter again
>>> print mykey
42
>>>