Reputation: 96458
How can I embed an IPython shell in my code and have it automatically display the line number and function in which it was invoked?
I currently have the following setup to embed IPython shells in my code:
from IPython.frontend.terminal.embed import InteractiveShellEmbed
from IPython.config.loader import Config
# Configure the prompt so that I know I am in a nested (embedded) shell
cfg = Config()
prompt_config = cfg.PromptManager
prompt_config.in_template = 'N.In <\\#>: '
prompt_config.in2_template = ' .\\D.: '
prompt_config.out_template = 'N.Out<\\#>: '
# Messages displayed when I drop into and exit the shell.
banner_msg = ("\n**Nested Interpreter:\n"
"Hit Ctrl-D to exit interpreter and continue program.\n"
"Note that if you use %kill_embedded, you can fully deactivate\n"
"This embedded instance so it will never turn on again")
exit_msg = '**Leaving Nested interpreter'
# Put ipshell() anywhere in your code where you want it to open.
ipshell = InteractiveShellEmbed(config=cfg, banner1=banner_msg, exit_msg=exit_msg)
This allows me to start a full IPython shell anywhere in my code by just using ipshell()
. For example, the following code:
a = 2
b = a
ipshell()
starts an IPython shell in the scope of the caller that allows me inspect the values of a
and b
.
What I would like to do is to automatically run the following code whenever I call ipshell()
:
frameinfo = getframeinfo(currentframe())
print 'Stopped at: ' + frameinfo.filename + ' ' + str(frameinfo.lineno)
This would always show the context where the IPython shell starts so that I know what file/function, etc. I am debugging.
Perhaps I could do this with a decorator, but all my attemps so far have failed, since I need ipshell()
to run within the original context (so that I have access to a
and b
from the IPython shell).
How can I accomplish this?
Upvotes: 3
Views: 1355
Reputation: 96458
You can call ipshell()
from within another user-defined function, e.g. ipsh()
from inspect import currentframe
def ipsh():
frame = currentframe().f_back
msg = 'Stopped at {0.f_code.co_filename} and line {0.f_lineno}'.format(frame)
ipshell(msg,stack_depth=2) # Go back one level!
Then use ipsh()
whenever you want to drop into the IPython shell.
stack_depth=2
asks ipshell
to go up one level when retrieving the namespace for the new IPython shell (the default is 1
).currentframe().f_back()
retrieves the previous frame so that you can print the line number and file of the location where ipsh()
is called.Upvotes: 6