Repository: ipython/ipython

Issue:
quit(keep_kernel=True) doesn't work
I'm using IPython 3.1.0



Discussion:
Which interface are you doing this in? In what way does it not work? Details are useful!

I was working on a notebook and needed to debug so I ran `ipython console --existing kernel-ad2bfcc4-5246-43f7-9ddf-3189506b23d8.json`.

Then I tried `quit(keep_kernel=True)` from the console IPython and the notebook kernel got restarted (everytime).

Can reproduce with the console also:

```
~/d/ipython (3.x) $ ipython console
IPython Console 3.2.0-dev

In [1]: quit?
Type:           ZMQExitAutocall
String form:    <IPython.core.autocall.ZMQExitAutocall object at 0x109fd0278>
File:           ~/dev/ipython/IPython/core/autocall.py
Signature:      quit(self, keep_kernel=False)
Docstring:
Exit IPython. Autocallable, so it needn't be explicitly called.

Parameters
----------
keep_kernel : bool
  If True, leave the kernel alive. Otherwise, tell the kernel to exit too
  (default).
Call signature: quit(keep_kernel=False)

In [3]: quit(keep_kernel=True)
~/d/ipython (3.x) $ ipython console --existing
[ZMQTerminalIPythonApp] CRITICAL | Could not find existing kernel connection file kernel*.json
```

Quit is an alias for exit, you can `/quit/exit/` 

From a quick glance at the code the handeling of keepkernel has never been implemented, 

Want to try  #8483 ?


Resolving patch:
diff --git a/IPython/terminal/console/app.py b/IPython/terminal/console/app.py
--- a/IPython/terminal/console/app.py
+++ b/IPython/terminal/console/app.py
@@ -113,6 +113,7 @@ def init_shell(self):
                         manager=self.kernel_manager,
                         client=self.kernel_client,
         )
+        self.shell.own_kernel = not self.existing
 
     def init_gui_pylab(self):
         # no-op, because we don't want to import matplotlib in the frontend.
diff --git a/IPython/terminal/console/interactiveshell.py b/IPython/terminal/console/interactiveshell.py
--- a/IPython/terminal/console/interactiveshell.py
+++ b/IPython/terminal/console/interactiveshell.py
@@ -212,6 +212,7 @@ def handle_execute_reply(self, msg_id, timeout=None):
                     elif source == 'set_next_input':
                         self.set_next_input(item['text'])
                     elif source == 'ask_exit':
+                        self.keepkernel=item.get('keepkernel', False)
                         self.ask_exit()
                
             elif status == 'error':
@@ -233,7 +234,7 @@ def handle_execute_reply(self, msg_id, timeout=None):
         Only relevant if include_other_output is True.
         """
     )
-    
+
     def from_here(self, msg):
         """Return whether a message is from this session"""
         return msg['parent_header'].get("session", self.session_id) == self.session_id
@@ -409,6 +410,7 @@ def double_int(sig,frame):
                 self.client.input(raw_data)
 
     def mainloop(self, display_banner=False):
+        self.keepkernel = False
         while True:
             try:
                 self.interact(display_banner=display_banner)
@@ -421,7 +423,15 @@ def mainloop(self, display_banner=False):
                 # handling seems rather unpredictable...
                 self.write("\nKeyboardInterrupt in interact()\n")
 
-        self.client.shutdown()
+        
+        if self.keepkernel and not self.own_kernel:
+            print('keeping kernel alive')
+        elif self.keepkernel and self.own_kernel :
+            print("owning kernel, cannot keep it alive")
+            self.client.shutdown()
+        else :
+            print("Shutting down kernel")
+            self.client.shutdown()
     
     def _banner1_default(self):
         return "IPython Console {version}\n".format(version=release.version)


Test patch: