Using IPython as an effective debugger
ipython, python
Solution
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.
Explanation:
- `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.
Problem
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?