Show More
@@ -43,6 +43,7 from IPython.terminal.console.completer import ZMQCompleter | |||||
43 | class ZMQTerminalInteractiveShell(TerminalInteractiveShell): |
|
43 | class ZMQTerminalInteractiveShell(TerminalInteractiveShell): | |
44 | """A subclass of TerminalInteractiveShell that uses the 0MQ kernel""" |
|
44 | """A subclass of TerminalInteractiveShell that uses the 0MQ kernel""" | |
45 | _executing = False |
|
45 | _executing = False | |
|
46 | _execution_state = Unicode('') | |||
46 |
|
47 | |||
47 | image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'), |
|
48 | image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'), | |
48 | config=True, help= |
|
49 | config=True, help= | |
@@ -151,32 +152,42 class ZMQTerminalInteractiveShell(TerminalInteractiveShell): | |||||
151 | # explicitly handle 'exit' command |
|
152 | # explicitly handle 'exit' command | |
152 | return self.ask_exit() |
|
153 | return self.ask_exit() | |
153 |
|
154 | |||
154 | self._executing = True |
|
|||
155 | # flush stale replies, which could have been ignored, due to missed heartbeats |
|
155 | # flush stale replies, which could have been ignored, due to missed heartbeats | |
156 | while self.client.shell_channel.msg_ready(): |
|
156 | while self.client.shell_channel.msg_ready(): | |
157 | self.client.shell_channel.get_msg() |
|
157 | self.client.shell_channel.get_msg() | |
158 | # shell_channel.execute takes 'hidden', which is the inverse of store_hist |
|
158 | # shell_channel.execute takes 'hidden', which is the inverse of store_hist | |
159 | msg_id = self.client.shell_channel.execute(cell, not store_history) |
|
159 | msg_id = self.client.shell_channel.execute(cell, not store_history) | |
160 | while not self.client.shell_channel.msg_ready() and self.client.is_alive(): |
|
160 | ||
|
161 | # first thing is wait for any side effects (output, stdin, etc.) | |||
|
162 | self._executing = True | |||
|
163 | self._execution_state = "busy" | |||
|
164 | while self._execution_state != 'idle' and self.client.is_alive(): | |||
161 | try: |
|
165 | try: | |
162 | self.handle_stdin_request(timeout=0.05) |
|
166 | self.handle_stdin_request(msg_id, timeout=0.05) | |
163 | except Empty: |
|
167 | except Empty: | |
164 | # display intermediate print statements, etc. |
|
168 | # display intermediate print statements, etc. | |
165 | self.handle_iopub() |
|
169 | self.handle_iopub(msg_id) | |
|
170 | pass | |||
|
171 | ||||
|
172 | # after all of that is done, wait for the execute reply | |||
|
173 | while self.client.is_alive(): | |||
|
174 | try: | |||
|
175 | self.handle_execute_reply(msg_id, timeout=0.05) | |||
|
176 | except Empty: | |||
166 | pass |
|
177 | pass | |
167 | if self.client.shell_channel.msg_ready(): |
|
178 | else: | |
168 | self.handle_execute_reply(msg_id) |
|
179 | break | |
169 | self._executing = False |
|
180 | self._executing = False | |
170 |
|
181 | |||
171 | #----------------- |
|
182 | #----------------- | |
172 | # message handlers |
|
183 | # message handlers | |
173 | #----------------- |
|
184 | #----------------- | |
174 |
|
185 | |||
175 | def handle_execute_reply(self, msg_id): |
|
186 | def handle_execute_reply(self, msg_id, timeout=None): | |
176 | msg = self.client.shell_channel.get_msg() |
|
187 | msg = self.client.shell_channel.get_msg(block=False, timeout=timeout) | |
177 | if msg["parent_header"].get("msg_id", None) == msg_id: |
|
188 | if msg["parent_header"].get("msg_id", None) == msg_id: | |
178 |
|
189 | |||
179 | self.handle_iopub() |
|
190 | self.handle_iopub(msg_id) | |
180 |
|
191 | |||
181 | content = msg["content"] |
|
192 | content = msg["content"] | |
182 | status = content['status'] |
|
193 | status = content['status'] | |
@@ -198,24 +209,25 class ZMQTerminalInteractiveShell(TerminalInteractiveShell): | |||||
198 | self.execution_count = int(content["execution_count"] + 1) |
|
209 | self.execution_count = int(content["execution_count"] + 1) | |
199 |
|
210 | |||
200 |
|
211 | |||
201 | def handle_iopub(self): |
|
212 | def handle_iopub(self, msg_id): | |
202 |
""" Method to proc |
|
213 | """ Method to process subscribe channel's messages | |
203 |
|
214 | |||
204 |
This method |
|
215 | This method consumes and processes messages on the IOPub channel, | |
205 |
|
|
216 | such as stdout, stderr, pyout and status. | |
206 |
|
217 | |||
207 | Arguments: |
|
218 | It only displays output that is caused by the given msg_id | |
208 | sub_msg: message receive from kernel in the sub socket channel |
|
|||
209 | capture by kernel manager. |
|
|||
210 | """ |
|
219 | """ | |
211 | while self.client.iopub_channel.msg_ready(): |
|
220 | while self.client.iopub_channel.msg_ready(): | |
212 | sub_msg = self.client.iopub_channel.get_msg() |
|
221 | sub_msg = self.client.iopub_channel.get_msg() | |
213 | msg_type = sub_msg['header']['msg_type'] |
|
222 | msg_type = sub_msg['header']['msg_type'] | |
214 | parent = sub_msg["parent_header"] |
|
223 | parent = sub_msg["parent_header"] | |
215 |
if (not parent) or |
|
224 | if (not parent) or msg_id == parent['msg_id']: | |
216 |
if msg_type == 'status' |
|
225 | if msg_type == 'status': | |
217 |
|
|
226 | state = self._execution_state = sub_msg["content"]["execution_state"] | |
218 | pass |
|
227 | # idle messages mean an individual sequence is complete, | |
|
228 | # so break out of consumption to allow other things to take over. | |||
|
229 | if state == 'idle': | |||
|
230 | break | |||
219 |
|
231 | |||
220 |
elif msg_type == 'stream' |
|
232 | elif msg_type == 'stream': | |
221 | if sub_msg["content"]["name"] == "stdout": |
|
233 | if sub_msg["content"]["name"] == "stdout": | |
@@ -240,6 +252,7 class ZMQTerminalInteractiveShell(TerminalInteractiveShell): | |||||
240 | elif msg_type == 'display_data': |
|
252 | elif msg_type == 'display_data': | |
241 | self.handle_rich_data(sub_msg["content"]["data"]) |
|
253 | self.handle_rich_data(sub_msg["content"]["data"]) | |
242 |
|
254 | |||
|
255 | ||||
243 | _imagemime = { |
|
256 | _imagemime = { | |
244 | 'image/png': 'png', |
|
257 | 'image/png': 'png', | |
245 | 'image/jpeg': 'jpeg', |
|
258 | 'image/jpeg': 'jpeg', | |
@@ -292,13 +305,13 class ZMQTerminalInteractiveShell(TerminalInteractiveShell): | |||||
292 | def handle_image_callable(self, data, mime): |
|
305 | def handle_image_callable(self, data, mime): | |
293 | self.callable_image_handler(data) |
|
306 | self.callable_image_handler(data) | |
294 |
|
307 | |||
295 | def handle_stdin_request(self, timeout=0.1): |
|
308 | def handle_stdin_request(self, msg_id, timeout=0.1): | |
296 | """ Method to capture raw_input |
|
309 | """ Method to capture raw_input | |
297 | """ |
|
310 | """ | |
298 | msg_rep = self.client.stdin_channel.get_msg(timeout=timeout) |
|
311 | msg_rep = self.client.stdin_channel.get_msg(timeout=timeout) | |
299 | # in case any iopub came while we were waiting: |
|
312 | # in case any iopub came while we were waiting: | |
300 | self.handle_iopub() |
|
313 | self.handle_iopub(msg_id) | |
301 |
if |
|
314 | if msg_id == msg_rep["parent_header"].get("msg_id"): | |
302 | # wrap SIGINT handler |
|
315 | # wrap SIGINT handler | |
303 | real_handler = signal.getsignal(signal.SIGINT) |
|
316 | real_handler = signal.getsignal(signal.SIGINT) | |
304 | def double_int(sig,frame): |
|
317 | def double_int(sig,frame): | |
@@ -373,7 +386,7 class ZMQTerminalInteractiveShell(TerminalInteractiveShell): | |||||
373 | # run a non-empty no-op, so that we don't get a prompt until |
|
386 | # run a non-empty no-op, so that we don't get a prompt until | |
374 | # we know the kernel is ready. This keeps the connection |
|
387 | # we know the kernel is ready. This keeps the connection | |
375 | # message above the first prompt. |
|
388 | # message above the first prompt. | |
376 |
if not self.wait_for_kernel( |
|
389 | if not self.wait_for_kernel(10): | |
377 | error("Kernel did not respond\n") |
|
390 | error("Kernel did not respond\n") | |
378 | return |
|
391 | return | |
379 |
|
392 | |||
@@ -394,7 +407,7 class ZMQTerminalInteractiveShell(TerminalInteractiveShell): | |||||
394 | if ans: |
|
407 | if ans: | |
395 | if self.manager: |
|
408 | if self.manager: | |
396 | self.manager.restart_kernel(True) |
|
409 | self.manager.restart_kernel(True) | |
397 |
self.wait_for_kernel( |
|
410 | self.wait_for_kernel(10) | |
398 | else: |
|
411 | else: | |
399 | self.exit_now = True |
|
412 | self.exit_now = True | |
400 | continue |
|
413 | continue |
General Comments 0
You need to be logged in to leave comments.
Login now