##// END OF EJS Templates
two-process interactive shell progress...
MinRK -
Show More
@@ -19,10 +19,12 b' from __future__ import print_function'
19
19
20 import bdb
20 import bdb
21 import sys
21 import sys
22 import time
22
23
23 from Queue import Empty
24 from Queue import Empty
24
25
25 from IPython.core.alias import AliasManager, AliasError
26 from IPython.core.alias import AliasManager, AliasError
27 from IPython.core import page
26 from IPython.utils.warn import warn, error, fatal
28 from IPython.utils.warn import warn, error, fatal
27 from IPython.utils import io
29 from IPython.utils import io
28
30
@@ -31,7 +33,8 b' from IPython.frontend.terminal.console.completer import ZMQCompleter'
31
33
32
34
33 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
35 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
34 """A subclass of TerminalInteractiveShell that """
36 """A subclass of TerminalInteractiveShell that uses the 0MQ kernel"""
37 _executing = False
35
38
36 def __init__(self, *args, **kwargs):
39 def __init__(self, *args, **kwargs):
37 self.km = kwargs.pop('kernel_manager')
40 self.km = kwargs.pop('kernel_manager')
@@ -78,14 +81,22 b' class ZMQTerminalInteractiveShell(TerminalInteractiveShell):'
78 if (not cell) or cell.isspace():
81 if (not cell) or cell.isspace():
79 return
82 return
80
83
84 self._executing = True
85 # flush stale replies, which could have been ignored, due to missed heartbeats
86 while self.km.shell_channel.msg_ready():
87 self.km.shell_channel.get_msg()
81 # shell_channel.execute takes 'hidden', which is the inverse of store_hist
88 # shell_channel.execute takes 'hidden', which is the inverse of store_hist
82 msg_id = self.km.shell_channel.execute(cell, not store_history)
89 msg_id = self.km.shell_channel.execute(cell, not store_history)
83 while not self.km.shell_channel.msg_ready():
90 while not self.km.shell_channel.msg_ready() and self.km.is_alive:
84 try:
91 try:
85 self.handle_stdin_request(timeout=0.05)
92 self.handle_stdin_request(timeout=0.05)
86 except Empty:
93 except Empty:
94 # display intermediate print statements, etc.
95 self.handle_iopub()
87 pass
96 pass
88 self.handle_execute_reply(msg_id)
97 if self.km.shell_channel.msg_ready():
98 self.handle_execute_reply(msg_id)
99 self._executing = False
89
100
90 #-----------------
101 #-----------------
91 # message handlers
102 # message handlers
@@ -93,15 +104,28 b' class ZMQTerminalInteractiveShell(TerminalInteractiveShell):'
93
104
94 def handle_execute_reply(self, msg_id):
105 def handle_execute_reply(self, msg_id):
95 msg = self.km.shell_channel.get_msg()
106 msg = self.km.shell_channel.get_msg()
96 if msg["parent_header"]["msg_id"] == msg_id:
107 if msg["parent_header"].get("msg_id", None) == msg_id:
97 if msg["content"]["status"] == 'ok' :
108
98 self.handle_iopub()
109 self.handle_iopub()
110
111 content = msg["content"]
112 status = content['status']
113
114 if status == 'aborted':
115 self.write('Aborted\n')
116 return
117 elif status == 'ok':
118 # print execution payloads as well:
119 for item in content["payload"]:
120 text = item.get('text', None)
121 if text:
122 page.page(text)
99
123
100 elif msg["content"]["status"] == 'error':
124 elif status == 'error':
101 for frame in msg["content"]["traceback"]:
125 for frame in content["traceback"]:
102 print(frame, file=io.stderr)
126 print(frame, file=io.stderr)
103
127
104 self.execution_count = int(msg["content"]["execution_count"] + 1)
128 self.execution_count = int(content["execution_count"] + 1)
105
129
106
130
107 def handle_iopub(self):
131 def handle_iopub(self):
@@ -162,6 +186,21 b' class ZMQTerminalInteractiveShell(TerminalInteractiveShell):'
162 # handling seems rather unpredictable...
186 # handling seems rather unpredictable...
163 self.write("\nKeyboardInterrupt in interact()\n")
187 self.write("\nKeyboardInterrupt in interact()\n")
164
188
189 def wait_for_kernel(self, timeout=None):
190 """method to wait for a kernel to be ready"""
191 tic = time.time()
192 self.km.hb_channel.unpause()
193 while True:
194 self.run_cell('1', False)
195 if self.km.hb_channel.is_beating():
196 # heart failure was not the reason this returned
197 break
198 else:
199 # heart failed
200 if timeout is not None and (time.time() - tic) > timeout:
201 return False
202 return True
203
165 def interact(self, display_banner=None):
204 def interact(self, display_banner=None):
166 """Closely emulate the interactive Python console."""
205 """Closely emulate the interactive Python console."""
167
206
@@ -179,6 +218,13 b' class ZMQTerminalInteractiveShell(TerminalInteractiveShell):'
179
218
180 more = False
219 more = False
181
220
221 # run a non-empty no-op, so that we don't get a prompt until
222 # we know the kernel is ready. This keeps the connection
223 # message above the first prompt.
224 if not self.wait_for_kernel(3):
225 error("Kernel did not respond\n")
226 return
227
182 if self.has_readline:
228 if self.has_readline:
183 self.readline_startup_hook(self.pre_readline)
229 self.readline_startup_hook(self.pre_readline)
184 # exit_now is set by a call to %Exit or %Quit, through the
230 # exit_now is set by a call to %Exit or %Quit, through the
@@ -186,27 +232,34 b' class ZMQTerminalInteractiveShell(TerminalInteractiveShell):'
186
232
187 while not self.exit_now:
233 while not self.exit_now:
188 if not self.km.is_alive:
234 if not self.km.is_alive:
189 ans = self.raw_input("kernel died, restart ([y]/n)?")
235 # kernel died, prompt for action or exit
190 if not ans.lower().startswith('n'):
236 action = "restart" if self.km.has_kernel else "wait for restart"
191 self.km.restart_kernel(True)
237 ans = self.ask_yes_no("kernel died, %s ([y]/n)?" % action, default='y')
238 if ans:
239 if self.km.has_kernel:
240 self.km.restart_kernel(True)
241 self.wait_for_kernel(3)
192 else:
242 else:
193 self.exit_now=True
243 self.exit_now = True
194 continue
244 continue
195 self.hooks.pre_prompt_hook()
196 if more:
197 try:
198 prompt = self.hooks.generate_prompt(True)
199 except:
200 self.showtraceback()
201 if self.autoindent:
202 self.rl_do_indent = True
203
204 else:
205 try:
206 prompt = self.hooks.generate_prompt(False)
207 except:
208 self.showtraceback()
209 try:
245 try:
246 # protect prompt block from KeyboardInterrupt
247 # when sitting on ctrl-C
248 self.hooks.pre_prompt_hook()
249 if more:
250 try:
251 prompt = self.hooks.generate_prompt(True)
252 except Exception:
253 self.showtraceback()
254 if self.autoindent:
255 self.rl_do_indent = True
256
257 else:
258 try:
259 prompt = self.hooks.generate_prompt(False)
260 except Exception:
261 self.showtraceback()
262
210 line = self.raw_input(prompt)
263 line = self.raw_input(prompt)
211 if self.exit_now:
264 if self.exit_now:
212 # quick exit on sys.std[in|out] close
265 # quick exit on sys.std[in|out] close
General Comments 0
You need to be logged in to leave comments. Login now