Skip to content


Use standard IPython startup instead of embed #74

wants to merge 2 commits into from

3 participants


Fixes #73


One reason I changed to use embed was it was part of the public API ( and consistent across versions (after 0.10). I agree and understand the reason not to use it (especially coming from an IPython developer). A couple issues I see with the current pull request:

  • IPython 1.x moved the ipapp module from IPython.frontend.terminal to IPython.terminal so we need some more conditional logic to get TerminalIPythonApp imported
  • Issue #36 was opened wanting the default profile loaded. I saw in the Django issue that this goes back and forth, and ultimately in issue #36 the request was to have the confirm_ext = False. I really don't want to expose another argument in Shell()'s constructor so I think this should just always be set to False (I figure 95%+ would prefer this, if not 100% :) ) or expose it as a Flask config parameter (maybe a key like SCRIPT_IPYTHON_CONFIRM_EXIT) but I don't know at this point if it even needs to be exposed.

Yeah as for #36 I agree there's no point to add an argument for confirm_ext, when a better way to do that would be via ipython config. The main thing should be to get user configuration loading correctly. I also realized my patch is broken as it doesn't seem to pull in the user context, so I need to figure that out as well. I'll see if I can add conditional support for the various versions also.


I just got a chance to look to see how Django is handling this and see that IPython 1.x now has a public API IPython.start_ipython() which looks like what we should be using moving forward (in case it's namespace moves again).

It also seems like you're doing a lot with the TerminalIPythonApp and TerminalInteractiveShell instances. Is all this needed / is there a cleaning way?


Unfortunately start_ipython() doesn't take user_ns (yet). See my stackoverflow question here:

Ideally ipython should be using TerminalIPythonApp. Unfortunately this is the best way I've found to do it while still supporting a custom user_ns and banner.


Seems to work for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 30 additions and 10 deletions.
  1. +30 −10 flask_script/
40 flask_script/
@@ -230,6 +230,35 @@ def get_context(self):
return self.make_context()
+ def ipython(self, context):
+ try:
+ # 0.10.x
+ from IPython.Shell import IPShellEmbed
+ ipshell = IPShellEmbed(banner=self.banner)
+ ipshell(global_ns=dict(), local_ns=context)
+ except ImportError:
+ # 0.12+
+ try:
+ from IPython.terminal import ipapp
+ except ImportError:
+ from IPython.frontend.terminal import ipapp
+ app = ipapp.TerminalIPythonApp.instance()
+ shell = ipapp.TerminalInteractiveShell.instance(
+ parent=app,
+ display_banner=False,
+ profile_dir=app.profile_dir,
+ ipython_dir=app.ipython_dir,
+ user_ns=context,
+ banner1=self.banner)
+ shell.configurables.append(app)
+ = shell
+ # shell has already been initialized, so we have to monkeypatch
+ # app.init_shell() to act as no-op
+ app.init_shell = lambda: None
+ app.initialize(argv=[])
+ app.start()
def run(self, no_ipython, no_bpython):
Runs the shell. If no_bpython is False or use_bpython is True, then
@@ -249,17 +278,8 @@ def run(self, no_ipython, no_bpython):
if not no_ipython:
- # Try IPython
- try:
- # 0.10.x
- from IPython.Shell import IPShellEmbed
- ipshell = IPShellEmbed(banner=self.banner)
- ipshell(global_ns=dict(), local_ns=context)
- except ImportError:
- # 0.12+
- from IPython import embed
- embed(banner1=self.banner, user_ns=context)
+ self.ipython(context)
except ImportError:
Something went wrong with that request. Please try again.