89

I'd like to programmatically exit a cell early in IPython Notebook. exit(0), however, kills the kernel.

Whats the proper way to do this? I'd prefer not to split the cell or manually halt execution.

watsonic
  • 3,155
  • 1
  • 27
  • 31
  • Can you explain why? If you're determined to only run half the code in a cell and then stop, I guess you could raise an exception, but I'm not sure what purpose that would serve. – Marius Jun 03 '14 at 00:14
  • @andi: that's incorrect. my question asks about halting execution of a single cell, not exiting the entire notebook! – watsonic Jun 03 '14 at 00:15
  • I am sorry, I was confused by your title exit from cell. Thought you meant notebook. –  Jun 03 '14 at 00:17
  • 1
    @Marius: it's a development strategy. i still like to run large blocks of code in one go inside a single cell, but often want to query variable state without running the whole thing. i'm relatively new to IPN and previously used exit(0) to do this when developing via command line scripts. – watsonic Jun 03 '14 at 00:18
  • @andi: can you unflag the duplicate? – watsonic Jun 03 '14 at 00:20
  • Actually I did. No Idea why it didn't. I think a Moderator will undo it after seeing the comments. Again, sorry about that. –  Jun 03 '14 at 00:21
  • Have a look here: http://stackoverflow.com/questions/7214799/can-i-stop-execution-of-current-module-in-ipython-without-leaving-ipython –  Jun 03 '14 at 00:30
  • @watsonic: The closest thing I can think of to your desired workflow would be to open up an Ipython console that uses the same kernel as the notebook with `ipython qtconsole --existing`, and copy-paste the lines you actually want to run from the notebook into the console when you want to quickly check things. – Marius Jun 03 '14 at 00:42
  • @Marius: thanks but thats a bit more involved than what i want to do (copy pasting etc). i see IPN as nice because its self contained. – watsonic Jun 03 '14 at 22:02
  • @andi i took inspiration from one [answer on that page](http://stackoverflow.com/a/18939511/695804) (which actually fails since its a pre-runtime syntax error) to produce an imperfect solution below. thanks! – watsonic Jun 03 '14 at 22:04
  • Great that it worked out. Nice effort and cool solution ;) –  Jun 04 '14 at 11:02
  • One way to do this is by putting your code into a function. You then use a `return None` to exit early - without throwing an error. – Charlie Dec 23 '19 at 13:14

6 Answers6

60

Slightly more "proper" options:

This will get you out of all but the worst try/except blocks.

raise KeyboardInterrupt

A little cleaner version of yours:

assert(False)

or simply:

raise

if you want to save a couple keystrokes.

Paul
  • 42,322
  • 15
  • 106
  • 123
  • 30
    The problem with this is that it's messy, you get a traceback. It would be nice to find a solution that ends execution quietly. – Stephen Jul 14 '17 at 19:30
57

To stop current and subsequent cells quietly:

class StopExecution(Exception):
    def _render_traceback_(self):
        pass

raise StopExecution
Samuel Rizzo
  • 2,811
  • 2
  • 20
  • 18
  • 4
    This perfect! Very simple and clean! – manu3d Sep 19 '19 at 08:37
  • 1
    very clean, thanks! Now I can do ``def exit(): raise StopExecution``. – Micha F. Jun 04 '21 at 16:27
  • 3
    As per https://github.com/ipython/ipython/blob/4f6e132d2fc56feabd9d87cac98906d3e5806d6a/IPython/core/interactiveshell.py#L1994 `_render_traceback_` is meant to return list of strings. So the method should probably do `return []` instead of `pass`. With `pass` I was hitting exceptions when using nbconvert. – Stan Oct 03 '22 at 12:24
25

I'm reposting my answer from here because the solution should apply to your question as well. It will...

  • not kill the kernel on exit
  • not display a full traceback (no traceback for use in IPython shell)
  • not force you to entrench code with try/excepts
  • work with or without IPython, without changes in code

Just import 'exit' from the code beneath into your jupyter notebook (IPython notebook) and calling 'exit()' should work. It will exit and letting you know that...

 An exception has occurred, use %tb to see the full traceback.

 IpyExit 

"""
# ipython_exit.py
Allows exit() to work if script is invoked with IPython without
raising NameError Exception. Keeps kernel alive.

Use: import variable 'exit' in target script with
     'from ipython_exit import exit'    
"""

import sys
from io import StringIO
from IPython import get_ipython


class IpyExit(SystemExit):
    """Exit Exception for IPython.

    Exception temporarily redirects stderr to buffer.
    """
    def __init__(self):
        # print("exiting")  # optionally print some message to stdout, too
        # ... or do other stuff before exit
        sys.stderr = StringIO()

    def __del__(self):
        sys.stderr.close()
        sys.stderr = sys.__stderr__  # restore from backup


def ipy_exit():
    raise IpyExit


if get_ipython():    # ...run with IPython
    exit = ipy_exit  # rebind to custom exit
else:
    exit = exit      # just make exit importable
Darkonaut
  • 20,186
  • 7
  • 54
  • 65
3

Not saying this is a good idea, but you can wrap the start of the cell in a single iteration for loop, then call 'break' to stop further execution.


for _ in range(1):
    # do some stuff
    if some_condition:
        break 

Morty
  • 1,436
  • 14
  • 12
  • I think this is an elegant solution. And, more, if we re-use the code in a function (using jupyter to tests/prototype), we just have to change the "break(s)" in return – am_technix Jan 06 '23 at 11:00
0

This is far from "proper" but one way to exit early is to create a runtime error. So instead of returning early from a script cleanly with exit(0) one can return uncleanly with something like

print(variable_to_query)
() + 1

which will run the code up until this point (completing the print statement) and then fail.

watsonic
  • 3,155
  • 1
  • 27
  • 31
-1

A simple answer would be to wrap the code inside a function and use return to stop execution

def func:
    if x==y:
        return
Nabeel Gm
  • 1
  • 3