How do I embed an IPython Interpreter into an application running in an IPython Qt Console

Erotemic picture Erotemic · Mar 1, 2013 · Viewed 18.2k times · Source

There are a few topics on this, but none with a satisfactory answer.

I have a python application running in an IPython qt console

http://ipython.org/ipython-doc/dev/interactive/qtconsole.html

When I encounter an error, I'd like to be able to interact with the code at that point.

    try: 
      raise Exception()
    except Exception as e:
        try: # use exception trick to pick up the current frame
            raise None
        except:
            frame = sys.exc_info()[2].tb_frame.f_back
        namespace = frame.f_globals.copy()
        namespace.update(frame.f_locals)
        import IPython
        IPython.embed_kernel(local_ns=namespace)  

I would think this would work, but I get an error:

RuntimeError: threads can only be started once

Answer

simon picture simon · Feb 2, 2014

I just use this:

from IPython import embed; embed()

works better than anything else for me :)


Update:

In celebration of this answer receiving 50 upvotes, here are the updates I've made to this snippet in the intervening six years since it was posted.

First, I now like to import and execute in a single statement, as I use black for all my python code these days and it reformats the original snippet in a way that doesn't make sense in this specific and unusual context. So:

 __import__("IPython").embed()

Given than I often use this inside a loop or a thread, it can be helpful to include a snippet that allows terminating the parent process (partly for convenience, and partly to remind myself of the best way to do it). os._exit is the best choice here, so my snippet includes this (same logic w/r/t using a single statement):

q = __import__("functools").partial(__import__("os")._exit, 0)

Then I can simply use q() if/when I want to exit the master process.

My full snippet (with # FIXME in case I would ever be likely to forget to remove it!) looks like this:

q = __import__("functools").partial(__import__("os")._exit, 0)  # FIXME
__import__("IPython").embed()  # FIXME