Skip to content
This repository

don't unregister interrupted post-exec functions #997

Closed
wants to merge 1 commit into from

3 participants

Min RK Fernando Perez Thomas Kluyver
Min RK
Owner

only unregister on real Exceptions.

also put close/cleanup for the inline backend calls inside finally block,
to ensure that the state is clean on the next round, even if show/flush is interrupted

closes gh-992

IPython/core/interactiveshell.py
... ...
@@ -2424,7 +2424,9 @@ class InteractiveShell(SingletonConfigurable, Magic):
2424 2424
                             continue
2425 2425
                         try:
2426 2426
                             func()
2427  
-                        except:
  2427
+                        except KeyboardInterrupt:
  2428
+                            self.write_err("\nKeyboardInterrupt\n")
  2429
+                        except Exception:
4
Thomas Kluyver Collaborator

Just to note: this will no longer catch SystemExit. I can't think of any valid reason why a post-execute function would raise SystemExit, and arguably the correct behaviour if it does is to crash, anyway.

Min RK Owner
minrk added a note November 13, 2011

I figured the right action is actually to exit, and that's what happens - not crash, clean exit. I can put it back if we want to catch SystemExit, but this made more sense to me:

def _exit():
    print "exiting"
    raise SystemExit
get_ipython().register_post_execute(_exit)
Thomas Kluyver Collaborator

I think that makes sense.

Min RK Owner
minrk added a note November 13, 2011

We do catch SystemExit elsewhere, so maybe it makes sense to catch it here. I think it's a question of whether we consider post_execute functions inside the interactive scope, where we don't allow exit by any means other than %exit, etc., or outside, where code has access to lower-level actions.

@fperez, preferences?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Min RK don't unregister interrupted post-exec functions
only unregister on real Exceptions.

also put close/cleanup for the inline backend calls inside `finally` block,
to ensure that the state is clean on the next round, even if show/flush is interrupted

closes gh-992
49d822a
Fernando Perez
Owner

I think the code is fine as-is, and since we're drowning in pull requests and this is really critical, I'm merging. We can fine-tune the behavior regarding SystemExit later on if we really find it necessary, but I honestly think we're fine as-is. It will catch a SystemExit and disable the registered function, which sounds pretty reasonable.

The important fix is handling sigint correctly, which I failed to take into account when I first wrote that code. Thanks!

I'll rebase to avoid the recursive merge and will push in a sec.

Fernando Perez
Owner

Merged in f3fe1c1, closing.

Fernando Perez fperez closed this November 20, 2011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Nov 13, 2011
Min RK don't unregister interrupted post-exec functions
only unregister on real Exceptions.

also put close/cleanup for the inline backend calls inside `finally` block,
to ensure that the state is clean on the next round, even if show/flush is interrupted

closes gh-992
49d822a
This page is out of date. Refresh to see the latest.
5  IPython/core/interactiveshell.py
@@ -2424,7 +2424,10 @@ def run_cell(self, raw_cell, store_history=False):
2424 2424
                             continue
2425 2425
                         try:
2426 2426
                             func()
2427  
-                        except:
  2427
+                        except KeyboardInterrupt:
  2428
+                            print >> io.stderr, "\nKeyboardInterrupt"
  2429
+                        except Exception:
  2430
+                            print >> io.stderr, "Disabling failed post-execution function: %s" % func
2428 2431
                             self.showtraceback()
2429 2432
                             # Deactivate failing function
2430 2433
                             self._post_execute[func] = False
28  IPython/zmq/pylab/backend_inline.py
@@ -97,11 +97,13 @@ def show(close=None):
97 97
     """
98 98
     if close is None:
99 99
         close = InlineBackend.instance().close_figures
100  
-    for figure_manager in Gcf.get_all_fig_managers():
101  
-        send_figure(figure_manager.canvas.figure)
102  
-    if close:
103  
-        matplotlib.pyplot.close('all')
104  
-    show._to_draw = []
  100
+    try:
  101
+        for figure_manager in Gcf.get_all_fig_managers():
  102
+            send_figure(figure_manager.canvas.figure)
  103
+    finally:
  104
+        show._to_draw = []
  105
+        if close:
  106
+            matplotlib.pyplot.close('all')
105 107
 
106 108
 
107 109
 
@@ -146,13 +148,15 @@ def flush_figures():
146 148
         # ignore the tracking, just draw and close all figures
147 149
         return show(True)
148 150
     
149  
-    # exclude any figures that were closed:
150  
-    active = set([fm.canvas.figure for fm in Gcf.get_all_fig_managers()])
151  
-    for fig in [ fig for fig in show._to_draw if fig in active ]:
152  
-        send_figure(fig)
153  
-    # clear flags for next round
154  
-    show._to_draw = []
155  
-    show._draw_called = False
  151
+    try:
  152
+        # exclude any figures that were closed:
  153
+        active = set([fm.canvas.figure for fm in Gcf.get_all_fig_managers()])
  154
+        for fig in [ fig for fig in show._to_draw if fig in active ]:
  155
+            send_figure(fig)
  156
+    finally:
  157
+        # clear flags for next round
  158
+        show._to_draw = []
  159
+        show._draw_called = False
156 160
 
157 161
 
158 162
 def send_figure(fig):
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.