##// END OF EJS Templates
Merge pull request #1620 from ivanov/pyin-execution-count...
Fernando Perez -
r6549:79d7b1ca merge
parent child Browse files
Show More
@@ -1,657 +1,657 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """A simple interactive kernel that talks to a frontend over 0MQ.
2 """A simple interactive kernel that talks to a frontend over 0MQ.
3
3
4 Things to do:
4 Things to do:
5
5
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
7 call set_parent on all the PUB objects with the message about to be executed.
7 call set_parent on all the PUB objects with the message about to be executed.
8 * Implement random port and security key logic.
8 * Implement random port and security key logic.
9 * Implement control messages.
9 * Implement control messages.
10 * Implement event loop and poll version.
10 * Implement event loop and poll version.
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Standard library imports.
18 # Standard library imports.
19 import __builtin__
19 import __builtin__
20 import atexit
20 import atexit
21 import sys
21 import sys
22 import time
22 import time
23 import traceback
23 import traceback
24 import logging
24 import logging
25 from signal import (
25 from signal import (
26 signal, default_int_handler, SIGINT, SIG_IGN
26 signal, default_int_handler, SIGINT, SIG_IGN
27 )
27 )
28 # System library imports.
28 # System library imports.
29 import zmq
29 import zmq
30
30
31 # Local imports.
31 # Local imports.
32 from IPython.core import pylabtools
32 from IPython.core import pylabtools
33 from IPython.config.configurable import Configurable
33 from IPython.config.configurable import Configurable
34 from IPython.config.application import boolean_flag, catch_config_error
34 from IPython.config.application import boolean_flag, catch_config_error
35 from IPython.core.application import ProfileDir
35 from IPython.core.application import ProfileDir
36 from IPython.core.error import StdinNotImplementedError
36 from IPython.core.error import StdinNotImplementedError
37 from IPython.core.shellapp import (
37 from IPython.core.shellapp import (
38 InteractiveShellApp, shell_flags, shell_aliases
38 InteractiveShellApp, shell_flags, shell_aliases
39 )
39 )
40 from IPython.utils import io
40 from IPython.utils import io
41 from IPython.utils import py3compat
41 from IPython.utils import py3compat
42 from IPython.utils.jsonutil import json_clean
42 from IPython.utils.jsonutil import json_clean
43 from IPython.utils.traitlets import (
43 from IPython.utils.traitlets import (
44 Any, Instance, Float, Dict, CaselessStrEnum
44 Any, Instance, Float, Dict, CaselessStrEnum
45 )
45 )
46
46
47 from entry_point import base_launch_kernel
47 from entry_point import base_launch_kernel
48 from kernelapp import KernelApp, kernel_flags, kernel_aliases
48 from kernelapp import KernelApp, kernel_flags, kernel_aliases
49 from session import Session, Message
49 from session import Session, Message
50 from zmqshell import ZMQInteractiveShell
50 from zmqshell import ZMQInteractiveShell
51
51
52
52
53 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
54 # Main kernel class
54 # Main kernel class
55 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
56
56
57 class Kernel(Configurable):
57 class Kernel(Configurable):
58
58
59 #---------------------------------------------------------------------------
59 #---------------------------------------------------------------------------
60 # Kernel interface
60 # Kernel interface
61 #---------------------------------------------------------------------------
61 #---------------------------------------------------------------------------
62
62
63 # attribute to override with a GUI
63 # attribute to override with a GUI
64 eventloop = Any(None)
64 eventloop = Any(None)
65
65
66 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
66 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
67 session = Instance(Session)
67 session = Instance(Session)
68 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
68 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
69 shell_socket = Instance('zmq.Socket')
69 shell_socket = Instance('zmq.Socket')
70 iopub_socket = Instance('zmq.Socket')
70 iopub_socket = Instance('zmq.Socket')
71 stdin_socket = Instance('zmq.Socket')
71 stdin_socket = Instance('zmq.Socket')
72 log = Instance(logging.Logger)
72 log = Instance(logging.Logger)
73
73
74 # Private interface
74 # Private interface
75
75
76 # Time to sleep after flushing the stdout/err buffers in each execute
76 # Time to sleep after flushing the stdout/err buffers in each execute
77 # cycle. While this introduces a hard limit on the minimal latency of the
77 # cycle. While this introduces a hard limit on the minimal latency of the
78 # execute cycle, it helps prevent output synchronization problems for
78 # execute cycle, it helps prevent output synchronization problems for
79 # clients.
79 # clients.
80 # Units are in seconds. The minimum zmq latency on local host is probably
80 # Units are in seconds. The minimum zmq latency on local host is probably
81 # ~150 microseconds, set this to 500us for now. We may need to increase it
81 # ~150 microseconds, set this to 500us for now. We may need to increase it
82 # a little if it's not enough after more interactive testing.
82 # a little if it's not enough after more interactive testing.
83 _execute_sleep = Float(0.0005, config=True)
83 _execute_sleep = Float(0.0005, config=True)
84
84
85 # Frequency of the kernel's event loop.
85 # Frequency of the kernel's event loop.
86 # Units are in seconds, kernel subclasses for GUI toolkits may need to
86 # Units are in seconds, kernel subclasses for GUI toolkits may need to
87 # adapt to milliseconds.
87 # adapt to milliseconds.
88 _poll_interval = Float(0.05, config=True)
88 _poll_interval = Float(0.05, config=True)
89
89
90 # If the shutdown was requested over the network, we leave here the
90 # If the shutdown was requested over the network, we leave here the
91 # necessary reply message so it can be sent by our registered atexit
91 # necessary reply message so it can be sent by our registered atexit
92 # handler. This ensures that the reply is only sent to clients truly at
92 # handler. This ensures that the reply is only sent to clients truly at
93 # the end of our shutdown process (which happens after the underlying
93 # the end of our shutdown process (which happens after the underlying
94 # IPython shell's own shutdown).
94 # IPython shell's own shutdown).
95 _shutdown_message = None
95 _shutdown_message = None
96
96
97 # This is a dict of port number that the kernel is listening on. It is set
97 # This is a dict of port number that the kernel is listening on. It is set
98 # by record_ports and used by connect_request.
98 # by record_ports and used by connect_request.
99 _recorded_ports = Dict()
99 _recorded_ports = Dict()
100
100
101
101
102
102
103 def __init__(self, **kwargs):
103 def __init__(self, **kwargs):
104 super(Kernel, self).__init__(**kwargs)
104 super(Kernel, self).__init__(**kwargs)
105
105
106 # Before we even start up the shell, register *first* our exit handlers
106 # Before we even start up the shell, register *first* our exit handlers
107 # so they come before the shell's
107 # so they come before the shell's
108 atexit.register(self._at_shutdown)
108 atexit.register(self._at_shutdown)
109
109
110 # Initialize the InteractiveShell subclass
110 # Initialize the InteractiveShell subclass
111 self.shell = ZMQInteractiveShell.instance(config=self.config,
111 self.shell = ZMQInteractiveShell.instance(config=self.config,
112 profile_dir = self.profile_dir,
112 profile_dir = self.profile_dir,
113 )
113 )
114 self.shell.displayhook.session = self.session
114 self.shell.displayhook.session = self.session
115 self.shell.displayhook.pub_socket = self.iopub_socket
115 self.shell.displayhook.pub_socket = self.iopub_socket
116 self.shell.display_pub.session = self.session
116 self.shell.display_pub.session = self.session
117 self.shell.display_pub.pub_socket = self.iopub_socket
117 self.shell.display_pub.pub_socket = self.iopub_socket
118
118
119 # TMP - hack while developing
119 # TMP - hack while developing
120 self.shell._reply_content = None
120 self.shell._reply_content = None
121
121
122 # Build dict of handlers for message types
122 # Build dict of handlers for message types
123 msg_types = [ 'execute_request', 'complete_request',
123 msg_types = [ 'execute_request', 'complete_request',
124 'object_info_request', 'history_request',
124 'object_info_request', 'history_request',
125 'connect_request', 'shutdown_request']
125 'connect_request', 'shutdown_request']
126 self.handlers = {}
126 self.handlers = {}
127 for msg_type in msg_types:
127 for msg_type in msg_types:
128 self.handlers[msg_type] = getattr(self, msg_type)
128 self.handlers[msg_type] = getattr(self, msg_type)
129
129
130 def do_one_iteration(self):
130 def do_one_iteration(self):
131 """Do one iteration of the kernel's evaluation loop.
131 """Do one iteration of the kernel's evaluation loop.
132 """
132 """
133 try:
133 try:
134 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
134 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
135 except Exception:
135 except Exception:
136 self.log.warn("Invalid Message:", exc_info=True)
136 self.log.warn("Invalid Message:", exc_info=True)
137 return
137 return
138 if msg is None:
138 if msg is None:
139 return
139 return
140
140
141 msg_type = msg['header']['msg_type']
141 msg_type = msg['header']['msg_type']
142
142
143 # This assert will raise in versions of zeromq 2.0.7 and lesser.
143 # This assert will raise in versions of zeromq 2.0.7 and lesser.
144 # We now require 2.0.8 or above, so we can uncomment for safety.
144 # We now require 2.0.8 or above, so we can uncomment for safety.
145 # print(ident,msg, file=sys.__stdout__)
145 # print(ident,msg, file=sys.__stdout__)
146 assert ident is not None, "Missing message part."
146 assert ident is not None, "Missing message part."
147
147
148 # Print some info about this message and leave a '--->' marker, so it's
148 # Print some info about this message and leave a '--->' marker, so it's
149 # easier to trace visually the message chain when debugging. Each
149 # easier to trace visually the message chain when debugging. Each
150 # handler prints its message at the end.
150 # handler prints its message at the end.
151 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
151 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
152 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
152 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
153
153
154 # Find and call actual handler for message
154 # Find and call actual handler for message
155 handler = self.handlers.get(msg_type, None)
155 handler = self.handlers.get(msg_type, None)
156 if handler is None:
156 if handler is None:
157 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
157 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
158 else:
158 else:
159 handler(ident, msg)
159 handler(ident, msg)
160
160
161 # Check whether we should exit, in case the incoming message set the
161 # Check whether we should exit, in case the incoming message set the
162 # exit flag on
162 # exit flag on
163 if self.shell.exit_now:
163 if self.shell.exit_now:
164 self.log.debug('\nExiting IPython kernel...')
164 self.log.debug('\nExiting IPython kernel...')
165 # We do a normal, clean exit, which allows any actions registered
165 # We do a normal, clean exit, which allows any actions registered
166 # via atexit (such as history saving) to take place.
166 # via atexit (such as history saving) to take place.
167 sys.exit(0)
167 sys.exit(0)
168
168
169
169
170 def start(self):
170 def start(self):
171 """ Start the kernel main loop.
171 """ Start the kernel main loop.
172 """
172 """
173 # a KeyboardInterrupt (SIGINT) can occur on any python statement, so
173 # a KeyboardInterrupt (SIGINT) can occur on any python statement, so
174 # let's ignore (SIG_IGN) them until we're in a place to handle them properly
174 # let's ignore (SIG_IGN) them until we're in a place to handle them properly
175 signal(SIGINT,SIG_IGN)
175 signal(SIGINT,SIG_IGN)
176 poller = zmq.Poller()
176 poller = zmq.Poller()
177 poller.register(self.shell_socket, zmq.POLLIN)
177 poller.register(self.shell_socket, zmq.POLLIN)
178 # loop while self.eventloop has not been overridden
178 # loop while self.eventloop has not been overridden
179 while self.eventloop is None:
179 while self.eventloop is None:
180 try:
180 try:
181 # scale by extra factor of 10, because there is no
181 # scale by extra factor of 10, because there is no
182 # reason for this to be anything less than ~ 0.1s
182 # reason for this to be anything less than ~ 0.1s
183 # since it is a real poller and will respond
183 # since it is a real poller and will respond
184 # to events immediately
184 # to events immediately
185
185
186 # double nested try/except, to properly catch KeyboardInterrupt
186 # double nested try/except, to properly catch KeyboardInterrupt
187 # due to pyzmq Issue #130
187 # due to pyzmq Issue #130
188 try:
188 try:
189 poller.poll(10*1000*self._poll_interval)
189 poller.poll(10*1000*self._poll_interval)
190 # restore raising of KeyboardInterrupt
190 # restore raising of KeyboardInterrupt
191 signal(SIGINT, default_int_handler)
191 signal(SIGINT, default_int_handler)
192 self.do_one_iteration()
192 self.do_one_iteration()
193 except:
193 except:
194 raise
194 raise
195 finally:
195 finally:
196 # prevent raising of KeyboardInterrupt
196 # prevent raising of KeyboardInterrupt
197 signal(SIGINT,SIG_IGN)
197 signal(SIGINT,SIG_IGN)
198 except KeyboardInterrupt:
198 except KeyboardInterrupt:
199 # Ctrl-C shouldn't crash the kernel
199 # Ctrl-C shouldn't crash the kernel
200 io.raw_print("KeyboardInterrupt caught in kernel")
200 io.raw_print("KeyboardInterrupt caught in kernel")
201 # stop ignoring sigint, now that we are out of our own loop,
201 # stop ignoring sigint, now that we are out of our own loop,
202 # we don't want to prevent future code from handling it
202 # we don't want to prevent future code from handling it
203 signal(SIGINT, default_int_handler)
203 signal(SIGINT, default_int_handler)
204 while self.eventloop is not None:
204 while self.eventloop is not None:
205 try:
205 try:
206 self.eventloop(self)
206 self.eventloop(self)
207 except KeyboardInterrupt:
207 except KeyboardInterrupt:
208 # Ctrl-C shouldn't crash the kernel
208 # Ctrl-C shouldn't crash the kernel
209 io.raw_print("KeyboardInterrupt caught in kernel")
209 io.raw_print("KeyboardInterrupt caught in kernel")
210 continue
210 continue
211 else:
211 else:
212 # eventloop exited cleanly, this means we should stop (right?)
212 # eventloop exited cleanly, this means we should stop (right?)
213 self.eventloop = None
213 self.eventloop = None
214 break
214 break
215
215
216
216
217 def record_ports(self, ports):
217 def record_ports(self, ports):
218 """Record the ports that this kernel is using.
218 """Record the ports that this kernel is using.
219
219
220 The creator of the Kernel instance must call this methods if they
220 The creator of the Kernel instance must call this methods if they
221 want the :meth:`connect_request` method to return the port numbers.
221 want the :meth:`connect_request` method to return the port numbers.
222 """
222 """
223 self._recorded_ports = ports
223 self._recorded_ports = ports
224
224
225 #---------------------------------------------------------------------------
225 #---------------------------------------------------------------------------
226 # Kernel request handlers
226 # Kernel request handlers
227 #---------------------------------------------------------------------------
227 #---------------------------------------------------------------------------
228
228
229 def _publish_pyin(self, code, parent):
229 def _publish_pyin(self, code, parent, execution_count):
230 """Publish the code request on the pyin stream."""
230 """Publish the code request on the pyin stream."""
231
231
232 self.session.send(self.iopub_socket, u'pyin', {u'code':code},
232 self.session.send(self.iopub_socket, u'pyin', {u'code':code,
233 parent=parent)
233 u'execution_count': execution_count}, parent=parent)
234
234
235 def execute_request(self, ident, parent):
235 def execute_request(self, ident, parent):
236
236
237 self.session.send(self.iopub_socket,
237 self.session.send(self.iopub_socket,
238 u'status',
238 u'status',
239 {u'execution_state':u'busy'},
239 {u'execution_state':u'busy'},
240 parent=parent )
240 parent=parent )
241
241
242 try:
242 try:
243 content = parent[u'content']
243 content = parent[u'content']
244 code = content[u'code']
244 code = content[u'code']
245 silent = content[u'silent']
245 silent = content[u'silent']
246 except:
246 except:
247 self.log.error("Got bad msg: ")
247 self.log.error("Got bad msg: ")
248 self.log.error(str(Message(parent)))
248 self.log.error(str(Message(parent)))
249 return
249 return
250
250
251 shell = self.shell # we'll need this a lot here
251 shell = self.shell # we'll need this a lot here
252
252
253 # Replace raw_input. Note that is not sufficient to replace
253 # Replace raw_input. Note that is not sufficient to replace
254 # raw_input in the user namespace.
254 # raw_input in the user namespace.
255 if content.get('allow_stdin', False):
255 if content.get('allow_stdin', False):
256 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
256 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
257 else:
257 else:
258 raw_input = lambda prompt='' : self._no_raw_input()
258 raw_input = lambda prompt='' : self._no_raw_input()
259
259
260 if py3compat.PY3:
260 if py3compat.PY3:
261 __builtin__.input = raw_input
261 __builtin__.input = raw_input
262 else:
262 else:
263 __builtin__.raw_input = raw_input
263 __builtin__.raw_input = raw_input
264
264
265 # Set the parent message of the display hook and out streams.
265 # Set the parent message of the display hook and out streams.
266 shell.displayhook.set_parent(parent)
266 shell.displayhook.set_parent(parent)
267 shell.display_pub.set_parent(parent)
267 shell.display_pub.set_parent(parent)
268 sys.stdout.set_parent(parent)
268 sys.stdout.set_parent(parent)
269 sys.stderr.set_parent(parent)
269 sys.stderr.set_parent(parent)
270
270
271 # Re-broadcast our input for the benefit of listening clients, and
271 # Re-broadcast our input for the benefit of listening clients, and
272 # start computing output
272 # start computing output
273 if not silent:
273 if not silent:
274 self._publish_pyin(code, parent)
274 self._publish_pyin(code, parent, shell.execution_count)
275
275
276 reply_content = {}
276 reply_content = {}
277 try:
277 try:
278 if silent:
278 if silent:
279 # run_code uses 'exec' mode, so no displayhook will fire, and it
279 # run_code uses 'exec' mode, so no displayhook will fire, and it
280 # doesn't call logging or history manipulations. Print
280 # doesn't call logging or history manipulations. Print
281 # statements in that code will obviously still execute.
281 # statements in that code will obviously still execute.
282 shell.run_code(code)
282 shell.run_code(code)
283 else:
283 else:
284 # FIXME: the shell calls the exception handler itself.
284 # FIXME: the shell calls the exception handler itself.
285 shell.run_cell(code, store_history=True)
285 shell.run_cell(code, store_history=True)
286 except:
286 except:
287 status = u'error'
287 status = u'error'
288 # FIXME: this code right now isn't being used yet by default,
288 # FIXME: this code right now isn't being used yet by default,
289 # because the run_cell() call above directly fires off exception
289 # because the run_cell() call above directly fires off exception
290 # reporting. This code, therefore, is only active in the scenario
290 # reporting. This code, therefore, is only active in the scenario
291 # where runlines itself has an unhandled exception. We need to
291 # where runlines itself has an unhandled exception. We need to
292 # uniformize this, for all exception construction to come from a
292 # uniformize this, for all exception construction to come from a
293 # single location in the codbase.
293 # single location in the codbase.
294 etype, evalue, tb = sys.exc_info()
294 etype, evalue, tb = sys.exc_info()
295 tb_list = traceback.format_exception(etype, evalue, tb)
295 tb_list = traceback.format_exception(etype, evalue, tb)
296 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
296 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
297 else:
297 else:
298 status = u'ok'
298 status = u'ok'
299
299
300 reply_content[u'status'] = status
300 reply_content[u'status'] = status
301
301
302 # Return the execution counter so clients can display prompts
302 # Return the execution counter so clients can display prompts
303 reply_content['execution_count'] = shell.execution_count -1
303 reply_content['execution_count'] = shell.execution_count -1
304
304
305 # FIXME - fish exception info out of shell, possibly left there by
305 # FIXME - fish exception info out of shell, possibly left there by
306 # runlines. We'll need to clean up this logic later.
306 # runlines. We'll need to clean up this logic later.
307 if shell._reply_content is not None:
307 if shell._reply_content is not None:
308 reply_content.update(shell._reply_content)
308 reply_content.update(shell._reply_content)
309 # reset after use
309 # reset after use
310 shell._reply_content = None
310 shell._reply_content = None
311
311
312 # At this point, we can tell whether the main code execution succeeded
312 # At this point, we can tell whether the main code execution succeeded
313 # or not. If it did, we proceed to evaluate user_variables/expressions
313 # or not. If it did, we proceed to evaluate user_variables/expressions
314 if reply_content['status'] == 'ok':
314 if reply_content['status'] == 'ok':
315 reply_content[u'user_variables'] = \
315 reply_content[u'user_variables'] = \
316 shell.user_variables(content[u'user_variables'])
316 shell.user_variables(content[u'user_variables'])
317 reply_content[u'user_expressions'] = \
317 reply_content[u'user_expressions'] = \
318 shell.user_expressions(content[u'user_expressions'])
318 shell.user_expressions(content[u'user_expressions'])
319 else:
319 else:
320 # If there was an error, don't even try to compute variables or
320 # If there was an error, don't even try to compute variables or
321 # expressions
321 # expressions
322 reply_content[u'user_variables'] = {}
322 reply_content[u'user_variables'] = {}
323 reply_content[u'user_expressions'] = {}
323 reply_content[u'user_expressions'] = {}
324
324
325 # Payloads should be retrieved regardless of outcome, so we can both
325 # Payloads should be retrieved regardless of outcome, so we can both
326 # recover partial output (that could have been generated early in a
326 # recover partial output (that could have been generated early in a
327 # block, before an error) and clear the payload system always.
327 # block, before an error) and clear the payload system always.
328 reply_content[u'payload'] = shell.payload_manager.read_payload()
328 reply_content[u'payload'] = shell.payload_manager.read_payload()
329 # Be agressive about clearing the payload because we don't want
329 # Be agressive about clearing the payload because we don't want
330 # it to sit in memory until the next execute_request comes in.
330 # it to sit in memory until the next execute_request comes in.
331 shell.payload_manager.clear_payload()
331 shell.payload_manager.clear_payload()
332
332
333 # Flush output before sending the reply.
333 # Flush output before sending the reply.
334 sys.stdout.flush()
334 sys.stdout.flush()
335 sys.stderr.flush()
335 sys.stderr.flush()
336 # FIXME: on rare occasions, the flush doesn't seem to make it to the
336 # FIXME: on rare occasions, the flush doesn't seem to make it to the
337 # clients... This seems to mitigate the problem, but we definitely need
337 # clients... This seems to mitigate the problem, but we definitely need
338 # to better understand what's going on.
338 # to better understand what's going on.
339 if self._execute_sleep:
339 if self._execute_sleep:
340 time.sleep(self._execute_sleep)
340 time.sleep(self._execute_sleep)
341
341
342 # Send the reply.
342 # Send the reply.
343 reply_content = json_clean(reply_content)
343 reply_content = json_clean(reply_content)
344 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
344 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
345 reply_content, parent, ident=ident)
345 reply_content, parent, ident=ident)
346 self.log.debug(str(reply_msg))
346 self.log.debug(str(reply_msg))
347
347
348 if reply_msg['content']['status'] == u'error':
348 if reply_msg['content']['status'] == u'error':
349 self._abort_queue()
349 self._abort_queue()
350
350
351 self.session.send(self.iopub_socket,
351 self.session.send(self.iopub_socket,
352 u'status',
352 u'status',
353 {u'execution_state':u'idle'},
353 {u'execution_state':u'idle'},
354 parent=parent )
354 parent=parent )
355
355
356 def complete_request(self, ident, parent):
356 def complete_request(self, ident, parent):
357 txt, matches = self._complete(parent)
357 txt, matches = self._complete(parent)
358 matches = {'matches' : matches,
358 matches = {'matches' : matches,
359 'matched_text' : txt,
359 'matched_text' : txt,
360 'status' : 'ok'}
360 'status' : 'ok'}
361 matches = json_clean(matches)
361 matches = json_clean(matches)
362 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
362 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
363 matches, parent, ident)
363 matches, parent, ident)
364 self.log.debug(str(completion_msg))
364 self.log.debug(str(completion_msg))
365
365
366 def object_info_request(self, ident, parent):
366 def object_info_request(self, ident, parent):
367 object_info = self.shell.object_inspect(parent['content']['oname'])
367 object_info = self.shell.object_inspect(parent['content']['oname'])
368 # Before we send this object over, we scrub it for JSON usage
368 # Before we send this object over, we scrub it for JSON usage
369 oinfo = json_clean(object_info)
369 oinfo = json_clean(object_info)
370 msg = self.session.send(self.shell_socket, 'object_info_reply',
370 msg = self.session.send(self.shell_socket, 'object_info_reply',
371 oinfo, parent, ident)
371 oinfo, parent, ident)
372 self.log.debug(msg)
372 self.log.debug(msg)
373
373
374 def history_request(self, ident, parent):
374 def history_request(self, ident, parent):
375 # We need to pull these out, as passing **kwargs doesn't work with
375 # We need to pull these out, as passing **kwargs doesn't work with
376 # unicode keys before Python 2.6.5.
376 # unicode keys before Python 2.6.5.
377 hist_access_type = parent['content']['hist_access_type']
377 hist_access_type = parent['content']['hist_access_type']
378 raw = parent['content']['raw']
378 raw = parent['content']['raw']
379 output = parent['content']['output']
379 output = parent['content']['output']
380 if hist_access_type == 'tail':
380 if hist_access_type == 'tail':
381 n = parent['content']['n']
381 n = parent['content']['n']
382 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
382 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
383 include_latest=True)
383 include_latest=True)
384
384
385 elif hist_access_type == 'range':
385 elif hist_access_type == 'range':
386 session = parent['content']['session']
386 session = parent['content']['session']
387 start = parent['content']['start']
387 start = parent['content']['start']
388 stop = parent['content']['stop']
388 stop = parent['content']['stop']
389 hist = self.shell.history_manager.get_range(session, start, stop,
389 hist = self.shell.history_manager.get_range(session, start, stop,
390 raw=raw, output=output)
390 raw=raw, output=output)
391
391
392 elif hist_access_type == 'search':
392 elif hist_access_type == 'search':
393 pattern = parent['content']['pattern']
393 pattern = parent['content']['pattern']
394 hist = self.shell.history_manager.search(pattern, raw=raw,
394 hist = self.shell.history_manager.search(pattern, raw=raw,
395 output=output)
395 output=output)
396
396
397 else:
397 else:
398 hist = []
398 hist = []
399 hist = list(hist)
399 hist = list(hist)
400 content = {'history' : hist}
400 content = {'history' : hist}
401 content = json_clean(content)
401 content = json_clean(content)
402 msg = self.session.send(self.shell_socket, 'history_reply',
402 msg = self.session.send(self.shell_socket, 'history_reply',
403 content, parent, ident)
403 content, parent, ident)
404 self.log.debug("Sending history reply with %i entries", len(hist))
404 self.log.debug("Sending history reply with %i entries", len(hist))
405
405
406 def connect_request(self, ident, parent):
406 def connect_request(self, ident, parent):
407 if self._recorded_ports is not None:
407 if self._recorded_ports is not None:
408 content = self._recorded_ports.copy()
408 content = self._recorded_ports.copy()
409 else:
409 else:
410 content = {}
410 content = {}
411 msg = self.session.send(self.shell_socket, 'connect_reply',
411 msg = self.session.send(self.shell_socket, 'connect_reply',
412 content, parent, ident)
412 content, parent, ident)
413 self.log.debug(msg)
413 self.log.debug(msg)
414
414
415 def shutdown_request(self, ident, parent):
415 def shutdown_request(self, ident, parent):
416 self.shell.exit_now = True
416 self.shell.exit_now = True
417 self._shutdown_message = self.session.msg(u'shutdown_reply',
417 self._shutdown_message = self.session.msg(u'shutdown_reply',
418 parent['content'], parent)
418 parent['content'], parent)
419 sys.exit(0)
419 sys.exit(0)
420
420
421 #---------------------------------------------------------------------------
421 #---------------------------------------------------------------------------
422 # Protected interface
422 # Protected interface
423 #---------------------------------------------------------------------------
423 #---------------------------------------------------------------------------
424
424
425 def _abort_queue(self):
425 def _abort_queue(self):
426 while True:
426 while True:
427 try:
427 try:
428 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
428 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
429 except Exception:
429 except Exception:
430 self.log.warn("Invalid Message:", exc_info=True)
430 self.log.warn("Invalid Message:", exc_info=True)
431 continue
431 continue
432 if msg is None:
432 if msg is None:
433 break
433 break
434 else:
434 else:
435 assert ident is not None, \
435 assert ident is not None, \
436 "Unexpected missing message part."
436 "Unexpected missing message part."
437
437
438 self.log.debug("Aborting:\n"+str(Message(msg)))
438 self.log.debug("Aborting:\n"+str(Message(msg)))
439 msg_type = msg['header']['msg_type']
439 msg_type = msg['header']['msg_type']
440 reply_type = msg_type.split('_')[0] + '_reply'
440 reply_type = msg_type.split('_')[0] + '_reply'
441 reply_msg = self.session.send(self.shell_socket, reply_type,
441 reply_msg = self.session.send(self.shell_socket, reply_type,
442 {'status' : 'aborted'}, msg, ident=ident)
442 {'status' : 'aborted'}, msg, ident=ident)
443 self.log.debug(reply_msg)
443 self.log.debug(reply_msg)
444 # We need to wait a bit for requests to come in. This can probably
444 # We need to wait a bit for requests to come in. This can probably
445 # be set shorter for true asynchronous clients.
445 # be set shorter for true asynchronous clients.
446 time.sleep(0.1)
446 time.sleep(0.1)
447
447
448 def _no_raw_input(self):
448 def _no_raw_input(self):
449 """Raise StdinNotImplentedError if active frontend doesn't support
449 """Raise StdinNotImplentedError if active frontend doesn't support
450 stdin."""
450 stdin."""
451 raise StdinNotImplementedError("raw_input was called, but this "
451 raise StdinNotImplementedError("raw_input was called, but this "
452 "frontend does not support stdin.")
452 "frontend does not support stdin.")
453
453
454 def _raw_input(self, prompt, ident, parent):
454 def _raw_input(self, prompt, ident, parent):
455 # Flush output before making the request.
455 # Flush output before making the request.
456 sys.stderr.flush()
456 sys.stderr.flush()
457 sys.stdout.flush()
457 sys.stdout.flush()
458
458
459 # Send the input request.
459 # Send the input request.
460 content = json_clean(dict(prompt=prompt))
460 content = json_clean(dict(prompt=prompt))
461 self.session.send(self.stdin_socket, u'input_request', content, parent,
461 self.session.send(self.stdin_socket, u'input_request', content, parent,
462 ident=ident)
462 ident=ident)
463
463
464 # Await a response.
464 # Await a response.
465 while True:
465 while True:
466 try:
466 try:
467 ident, reply = self.session.recv(self.stdin_socket, 0)
467 ident, reply = self.session.recv(self.stdin_socket, 0)
468 except Exception:
468 except Exception:
469 self.log.warn("Invalid Message:", exc_info=True)
469 self.log.warn("Invalid Message:", exc_info=True)
470 else:
470 else:
471 break
471 break
472 try:
472 try:
473 value = reply['content']['value']
473 value = reply['content']['value']
474 except:
474 except:
475 self.log.error("Got bad raw_input reply: ")
475 self.log.error("Got bad raw_input reply: ")
476 self.log.error(str(Message(parent)))
476 self.log.error(str(Message(parent)))
477 value = ''
477 value = ''
478 if value == '\x04':
478 if value == '\x04':
479 # EOF
479 # EOF
480 raise EOFError
480 raise EOFError
481 return value
481 return value
482
482
483 def _complete(self, msg):
483 def _complete(self, msg):
484 c = msg['content']
484 c = msg['content']
485 try:
485 try:
486 cpos = int(c['cursor_pos'])
486 cpos = int(c['cursor_pos'])
487 except:
487 except:
488 # If we don't get something that we can convert to an integer, at
488 # If we don't get something that we can convert to an integer, at
489 # least attempt the completion guessing the cursor is at the end of
489 # least attempt the completion guessing the cursor is at the end of
490 # the text, if there's any, and otherwise of the line
490 # the text, if there's any, and otherwise of the line
491 cpos = len(c['text'])
491 cpos = len(c['text'])
492 if cpos==0:
492 if cpos==0:
493 cpos = len(c['line'])
493 cpos = len(c['line'])
494 return self.shell.complete(c['text'], c['line'], cpos)
494 return self.shell.complete(c['text'], c['line'], cpos)
495
495
496 def _object_info(self, context):
496 def _object_info(self, context):
497 symbol, leftover = self._symbol_from_context(context)
497 symbol, leftover = self._symbol_from_context(context)
498 if symbol is not None and not leftover:
498 if symbol is not None and not leftover:
499 doc = getattr(symbol, '__doc__', '')
499 doc = getattr(symbol, '__doc__', '')
500 else:
500 else:
501 doc = ''
501 doc = ''
502 object_info = dict(docstring = doc)
502 object_info = dict(docstring = doc)
503 return object_info
503 return object_info
504
504
505 def _symbol_from_context(self, context):
505 def _symbol_from_context(self, context):
506 if not context:
506 if not context:
507 return None, context
507 return None, context
508
508
509 base_symbol_string = context[0]
509 base_symbol_string = context[0]
510 symbol = self.shell.user_ns.get(base_symbol_string, None)
510 symbol = self.shell.user_ns.get(base_symbol_string, None)
511 if symbol is None:
511 if symbol is None:
512 symbol = __builtin__.__dict__.get(base_symbol_string, None)
512 symbol = __builtin__.__dict__.get(base_symbol_string, None)
513 if symbol is None:
513 if symbol is None:
514 return None, context
514 return None, context
515
515
516 context = context[1:]
516 context = context[1:]
517 for i, name in enumerate(context):
517 for i, name in enumerate(context):
518 new_symbol = getattr(symbol, name, None)
518 new_symbol = getattr(symbol, name, None)
519 if new_symbol is None:
519 if new_symbol is None:
520 return symbol, context[i:]
520 return symbol, context[i:]
521 else:
521 else:
522 symbol = new_symbol
522 symbol = new_symbol
523
523
524 return symbol, []
524 return symbol, []
525
525
526 def _at_shutdown(self):
526 def _at_shutdown(self):
527 """Actions taken at shutdown by the kernel, called by python's atexit.
527 """Actions taken at shutdown by the kernel, called by python's atexit.
528 """
528 """
529 # io.rprint("Kernel at_shutdown") # dbg
529 # io.rprint("Kernel at_shutdown") # dbg
530 if self._shutdown_message is not None:
530 if self._shutdown_message is not None:
531 self.session.send(self.shell_socket, self._shutdown_message)
531 self.session.send(self.shell_socket, self._shutdown_message)
532 self.session.send(self.iopub_socket, self._shutdown_message)
532 self.session.send(self.iopub_socket, self._shutdown_message)
533 self.log.debug(str(self._shutdown_message))
533 self.log.debug(str(self._shutdown_message))
534 # A very short sleep to give zmq time to flush its message buffers
534 # A very short sleep to give zmq time to flush its message buffers
535 # before Python truly shuts down.
535 # before Python truly shuts down.
536 time.sleep(0.01)
536 time.sleep(0.01)
537
537
538 #-----------------------------------------------------------------------------
538 #-----------------------------------------------------------------------------
539 # Aliases and Flags for the IPKernelApp
539 # Aliases and Flags for the IPKernelApp
540 #-----------------------------------------------------------------------------
540 #-----------------------------------------------------------------------------
541
541
542 flags = dict(kernel_flags)
542 flags = dict(kernel_flags)
543 flags.update(shell_flags)
543 flags.update(shell_flags)
544
544
545 addflag = lambda *args: flags.update(boolean_flag(*args))
545 addflag = lambda *args: flags.update(boolean_flag(*args))
546
546
547 flags['pylab'] = (
547 flags['pylab'] = (
548 {'IPKernelApp' : {'pylab' : 'auto'}},
548 {'IPKernelApp' : {'pylab' : 'auto'}},
549 """Pre-load matplotlib and numpy for interactive use with
549 """Pre-load matplotlib and numpy for interactive use with
550 the default matplotlib backend."""
550 the default matplotlib backend."""
551 )
551 )
552
552
553 aliases = dict(kernel_aliases)
553 aliases = dict(kernel_aliases)
554 aliases.update(shell_aliases)
554 aliases.update(shell_aliases)
555
555
556 # it's possible we don't want short aliases for *all* of these:
556 # it's possible we don't want short aliases for *all* of these:
557 aliases.update(dict(
557 aliases.update(dict(
558 pylab='IPKernelApp.pylab',
558 pylab='IPKernelApp.pylab',
559 ))
559 ))
560
560
561 #-----------------------------------------------------------------------------
561 #-----------------------------------------------------------------------------
562 # The IPKernelApp class
562 # The IPKernelApp class
563 #-----------------------------------------------------------------------------
563 #-----------------------------------------------------------------------------
564
564
565 class IPKernelApp(KernelApp, InteractiveShellApp):
565 class IPKernelApp(KernelApp, InteractiveShellApp):
566 name = 'ipkernel'
566 name = 'ipkernel'
567
567
568 aliases = Dict(aliases)
568 aliases = Dict(aliases)
569 flags = Dict(flags)
569 flags = Dict(flags)
570 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
570 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
571 # configurables
571 # configurables
572 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
572 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
573 config=True,
573 config=True,
574 help="""Pre-load matplotlib and numpy for interactive use,
574 help="""Pre-load matplotlib and numpy for interactive use,
575 selecting a particular matplotlib backend and loop integration.
575 selecting a particular matplotlib backend and loop integration.
576 """
576 """
577 )
577 )
578
578
579 @catch_config_error
579 @catch_config_error
580 def initialize(self, argv=None):
580 def initialize(self, argv=None):
581 super(IPKernelApp, self).initialize(argv)
581 super(IPKernelApp, self).initialize(argv)
582 self.init_shell()
582 self.init_shell()
583 self.init_extensions()
583 self.init_extensions()
584 self.init_code()
584 self.init_code()
585
585
586 def init_kernel(self):
586 def init_kernel(self):
587
587
588 kernel = Kernel(config=self.config, session=self.session,
588 kernel = Kernel(config=self.config, session=self.session,
589 shell_socket=self.shell_socket,
589 shell_socket=self.shell_socket,
590 iopub_socket=self.iopub_socket,
590 iopub_socket=self.iopub_socket,
591 stdin_socket=self.stdin_socket,
591 stdin_socket=self.stdin_socket,
592 log=self.log,
592 log=self.log,
593 profile_dir=self.profile_dir,
593 profile_dir=self.profile_dir,
594 )
594 )
595 self.kernel = kernel
595 self.kernel = kernel
596 kernel.record_ports(self.ports)
596 kernel.record_ports(self.ports)
597 shell = kernel.shell
597 shell = kernel.shell
598 if self.pylab:
598 if self.pylab:
599 try:
599 try:
600 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
600 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
601 shell.enable_pylab(gui, import_all=self.pylab_import_all)
601 shell.enable_pylab(gui, import_all=self.pylab_import_all)
602 except Exception:
602 except Exception:
603 self.log.error("Pylab initialization failed", exc_info=True)
603 self.log.error("Pylab initialization failed", exc_info=True)
604 # print exception straight to stdout, because normally
604 # print exception straight to stdout, because normally
605 # _showtraceback associates the reply with an execution,
605 # _showtraceback associates the reply with an execution,
606 # which means frontends will never draw it, as this exception
606 # which means frontends will never draw it, as this exception
607 # is not associated with any execute request.
607 # is not associated with any execute request.
608
608
609 # replace pyerr-sending traceback with stdout
609 # replace pyerr-sending traceback with stdout
610 _showtraceback = shell._showtraceback
610 _showtraceback = shell._showtraceback
611 def print_tb(etype, evalue, stb):
611 def print_tb(etype, evalue, stb):
612 print ("Error initializing pylab, pylab mode will not "
612 print ("Error initializing pylab, pylab mode will not "
613 "be active", file=io.stderr)
613 "be active", file=io.stderr)
614 print (shell.InteractiveTB.stb2text(stb), file=io.stdout)
614 print (shell.InteractiveTB.stb2text(stb), file=io.stdout)
615 shell._showtraceback = print_tb
615 shell._showtraceback = print_tb
616
616
617 # send the traceback over stdout
617 # send the traceback over stdout
618 shell.showtraceback(tb_offset=0)
618 shell.showtraceback(tb_offset=0)
619
619
620 # restore proper _showtraceback method
620 # restore proper _showtraceback method
621 shell._showtraceback = _showtraceback
621 shell._showtraceback = _showtraceback
622
622
623
623
624 def init_shell(self):
624 def init_shell(self):
625 self.shell = self.kernel.shell
625 self.shell = self.kernel.shell
626 self.shell.configurables.append(self)
626 self.shell.configurables.append(self)
627
627
628
628
629 #-----------------------------------------------------------------------------
629 #-----------------------------------------------------------------------------
630 # Kernel main and launch functions
630 # Kernel main and launch functions
631 #-----------------------------------------------------------------------------
631 #-----------------------------------------------------------------------------
632
632
633 def launch_kernel(*args, **kwargs):
633 def launch_kernel(*args, **kwargs):
634 """Launches a localhost IPython kernel, binding to the specified ports.
634 """Launches a localhost IPython kernel, binding to the specified ports.
635
635
636 This function simply calls entry_point.base_launch_kernel with the right
636 This function simply calls entry_point.base_launch_kernel with the right
637 first command to start an ipkernel. See base_launch_kernel for arguments.
637 first command to start an ipkernel. See base_launch_kernel for arguments.
638
638
639 Returns
639 Returns
640 -------
640 -------
641 A tuple of form:
641 A tuple of form:
642 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
642 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
643 where kernel_process is a Popen object and the ports are integers.
643 where kernel_process is a Popen object and the ports are integers.
644 """
644 """
645 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
645 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
646 *args, **kwargs)
646 *args, **kwargs)
647
647
648
648
649 def main():
649 def main():
650 """Run an IPKernel as an application"""
650 """Run an IPKernel as an application"""
651 app = IPKernelApp.instance()
651 app = IPKernelApp.instance()
652 app.initialize()
652 app.initialize()
653 app.start()
653 app.start()
654
654
655
655
656 if __name__ == '__main__':
656 if __name__ == '__main__':
657 main()
657 main()
@@ -1,949 +1,954 b''
1 .. _messaging:
1 .. _messaging:
2
2
3 ======================
3 ======================
4 Messaging in IPython
4 Messaging in IPython
5 ======================
5 ======================
6
6
7
7
8 Introduction
8 Introduction
9 ============
9 ============
10
10
11 This document explains the basic communications design and messaging
11 This document explains the basic communications design and messaging
12 specification for how the various IPython objects interact over a network
12 specification for how the various IPython objects interact over a network
13 transport. The current implementation uses the ZeroMQ_ library for messaging
13 transport. The current implementation uses the ZeroMQ_ library for messaging
14 within and between hosts.
14 within and between hosts.
15
15
16 .. Note::
16 .. Note::
17
17
18 This document should be considered the authoritative description of the
18 This document should be considered the authoritative description of the
19 IPython messaging protocol, and all developers are strongly encouraged to
19 IPython messaging protocol, and all developers are strongly encouraged to
20 keep it updated as the implementation evolves, so that we have a single
20 keep it updated as the implementation evolves, so that we have a single
21 common reference for all protocol details.
21 common reference for all protocol details.
22
22
23 The basic design is explained in the following diagram:
23 The basic design is explained in the following diagram:
24
24
25 .. image:: figs/frontend-kernel.png
25 .. image:: figs/frontend-kernel.png
26 :width: 450px
26 :width: 450px
27 :alt: IPython kernel/frontend messaging architecture.
27 :alt: IPython kernel/frontend messaging architecture.
28 :align: center
28 :align: center
29 :target: ../_images/frontend-kernel.png
29 :target: ../_images/frontend-kernel.png
30
30
31 A single kernel can be simultaneously connected to one or more frontends. The
31 A single kernel can be simultaneously connected to one or more frontends. The
32 kernel has three sockets that serve the following functions:
32 kernel has three sockets that serve the following functions:
33
33
34 1. stdin: this ROUTER socket is connected to all frontends, and it allows
34 1. stdin: this ROUTER socket is connected to all frontends, and it allows
35 the kernel to request input from the active frontend when :func:`raw_input` is called.
35 the kernel to request input from the active frontend when :func:`raw_input` is called.
36 The frontend that executed the code has a DEALER socket that acts as a 'virtual keyboard'
36 The frontend that executed the code has a DEALER socket that acts as a 'virtual keyboard'
37 for the kernel while this communication is happening (illustrated in the
37 for the kernel while this communication is happening (illustrated in the
38 figure by the black outline around the central keyboard). In practice,
38 figure by the black outline around the central keyboard). In practice,
39 frontends may display such kernel requests using a special input widget or
39 frontends may display such kernel requests using a special input widget or
40 otherwise indicating that the user is to type input for the kernel instead
40 otherwise indicating that the user is to type input for the kernel instead
41 of normal commands in the frontend.
41 of normal commands in the frontend.
42
42
43 2. Shell: this single ROUTER socket allows multiple incoming connections from
43 2. Shell: this single ROUTER socket allows multiple incoming connections from
44 frontends, and this is the socket where requests for code execution, object
44 frontends, and this is the socket where requests for code execution, object
45 information, prompts, etc. are made to the kernel by any frontend. The
45 information, prompts, etc. are made to the kernel by any frontend. The
46 communication on this socket is a sequence of request/reply actions from
46 communication on this socket is a sequence of request/reply actions from
47 each frontend and the kernel.
47 each frontend and the kernel.
48
48
49 3. IOPub: this socket is the 'broadcast channel' where the kernel publishes all
49 3. IOPub: this socket is the 'broadcast channel' where the kernel publishes all
50 side effects (stdout, stderr, etc.) as well as the requests coming from any
50 side effects (stdout, stderr, etc.) as well as the requests coming from any
51 client over the shell socket and its own requests on the stdin socket. There
51 client over the shell socket and its own requests on the stdin socket. There
52 are a number of actions in Python which generate side effects: :func:`print`
52 are a number of actions in Python which generate side effects: :func:`print`
53 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
53 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
54 a multi-client scenario, we want all frontends to be able to know what each
54 a multi-client scenario, we want all frontends to be able to know what each
55 other has sent to the kernel (this can be useful in collaborative scenarios,
55 other has sent to the kernel (this can be useful in collaborative scenarios,
56 for example). This socket allows both side effects and the information
56 for example). This socket allows both side effects and the information
57 about communications taking place with one client over the shell channel
57 about communications taking place with one client over the shell channel
58 to be made available to all clients in a uniform manner.
58 to be made available to all clients in a uniform manner.
59
59
60 All messages are tagged with enough information (details below) for clients
60 All messages are tagged with enough information (details below) for clients
61 to know which messages come from their own interaction with the kernel and
61 to know which messages come from their own interaction with the kernel and
62 which ones are from other clients, so they can display each type
62 which ones are from other clients, so they can display each type
63 appropriately.
63 appropriately.
64
64
65 The actual format of the messages allowed on each of these channels is
65 The actual format of the messages allowed on each of these channels is
66 specified below. Messages are dicts of dicts with string keys and values that
66 specified below. Messages are dicts of dicts with string keys and values that
67 are reasonably representable in JSON. Our current implementation uses JSON
67 are reasonably representable in JSON. Our current implementation uses JSON
68 explicitly as its message format, but this shouldn't be considered a permanent
68 explicitly as its message format, but this shouldn't be considered a permanent
69 feature. As we've discovered that JSON has non-trivial performance issues due
69 feature. As we've discovered that JSON has non-trivial performance issues due
70 to excessive copying, we may in the future move to a pure pickle-based raw
70 to excessive copying, we may in the future move to a pure pickle-based raw
71 message format. However, it should be possible to easily convert from the raw
71 message format. However, it should be possible to easily convert from the raw
72 objects to JSON, since we may have non-python clients (e.g. a web frontend).
72 objects to JSON, since we may have non-python clients (e.g. a web frontend).
73 As long as it's easy to make a JSON version of the objects that is a faithful
73 As long as it's easy to make a JSON version of the objects that is a faithful
74 representation of all the data, we can communicate with such clients.
74 representation of all the data, we can communicate with such clients.
75
75
76 .. Note::
76 .. Note::
77
77
78 Not all of these have yet been fully fleshed out, but the key ones are, see
78 Not all of these have yet been fully fleshed out, but the key ones are, see
79 kernel and frontend files for actual implementation details.
79 kernel and frontend files for actual implementation details.
80
80
81
81
82 Python functional API
82 Python functional API
83 =====================
83 =====================
84
84
85 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
85 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
86 should develop, at a few key points, functional forms of all the requests that
86 should develop, at a few key points, functional forms of all the requests that
87 take arguments in this manner and automatically construct the necessary dict
87 take arguments in this manner and automatically construct the necessary dict
88 for sending.
88 for sending.
89
89
90
90
91 General Message Format
91 General Message Format
92 ======================
92 ======================
93
93
94 All messages send or received by any IPython process should have the following
94 All messages send or received by any IPython process should have the following
95 generic structure::
95 generic structure::
96
96
97 {
97 {
98 # The message header contains a pair of unique identifiers for the
98 # The message header contains a pair of unique identifiers for the
99 # originating session and the actual message id, in addition to the
99 # originating session and the actual message id, in addition to the
100 # username for the process that generated the message. This is useful in
100 # username for the process that generated the message. This is useful in
101 # collaborative settings where multiple users may be interacting with the
101 # collaborative settings where multiple users may be interacting with the
102 # same kernel simultaneously, so that frontends can label the various
102 # same kernel simultaneously, so that frontends can label the various
103 # messages in a meaningful way.
103 # messages in a meaningful way.
104 'header' : {
104 'header' : {
105 'msg_id' : uuid,
105 'msg_id' : uuid,
106 'username' : str,
106 'username' : str,
107 'session' : uuid
107 'session' : uuid
108 # All recognized message type strings are listed below.
108 # All recognized message type strings are listed below.
109 'msg_type' : str,
109 'msg_type' : str,
110 },
110 },
111 # The msg's unique identifier and type are stored in the header, but
111 # The msg's unique identifier and type are stored in the header, but
112 # are also accessible at the top-level for convenience.
112 # are also accessible at the top-level for convenience.
113 'msg_id' : uuid,
113 'msg_id' : uuid,
114 'msg_type' : str,
114 'msg_type' : str,
115
115
116 # In a chain of messages, the header from the parent is copied so that
116 # In a chain of messages, the header from the parent is copied so that
117 # clients can track where messages come from.
117 # clients can track where messages come from.
118 'parent_header' : dict,
118 'parent_header' : dict,
119
119
120 # The actual content of the message must be a dict, whose structure
120 # The actual content of the message must be a dict, whose structure
121 # depends on the message type.x
121 # depends on the message type.x
122 'content' : dict,
122 'content' : dict,
123 }
123 }
124
124
125 For each message type, the actual content will differ and all existing message
125 For each message type, the actual content will differ and all existing message
126 types are specified in what follows of this document.
126 types are specified in what follows of this document.
127
127
128
128
129 Messages on the shell ROUTER/DEALER sockets
129 Messages on the shell ROUTER/DEALER sockets
130 ===========================================
130 ===========================================
131
131
132 .. _execute:
132 .. _execute:
133
133
134 Execute
134 Execute
135 -------
135 -------
136
136
137 This message type is used by frontends to ask the kernel to execute code on
137 This message type is used by frontends to ask the kernel to execute code on
138 behalf of the user, in a namespace reserved to the user's variables (and thus
138 behalf of the user, in a namespace reserved to the user's variables (and thus
139 separate from the kernel's own internal code and variables).
139 separate from the kernel's own internal code and variables).
140
140
141 Message type: ``execute_request``::
141 Message type: ``execute_request``::
142
142
143 content = {
143 content = {
144 # Source code to be executed by the kernel, one or more lines.
144 # Source code to be executed by the kernel, one or more lines.
145 'code' : str,
145 'code' : str,
146
146
147 # A boolean flag which, if True, signals the kernel to execute
147 # A boolean flag which, if True, signals the kernel to execute
148 # this code as quietly as possible. This means that the kernel
148 # this code as quietly as possible. This means that the kernel
149 # will compile the code with 'exec' instead of 'single' (so
149 # will compile the code with 'exec' instead of 'single' (so
150 # sys.displayhook will not fire), and will *not*:
150 # sys.displayhook will not fire), and will *not*:
151 # - broadcast exceptions on the PUB socket
151 # - broadcast exceptions on the PUB socket
152 # - do any logging
152 # - do any logging
153 # - populate any history
153 # - populate any history
154 #
154 #
155 # The default is False.
155 # The default is False.
156 'silent' : bool,
156 'silent' : bool,
157
157
158 # A list of variable names from the user's namespace to be retrieved. What
158 # A list of variable names from the user's namespace to be retrieved. What
159 # returns is a JSON string of the variable's repr(), not a python object.
159 # returns is a JSON string of the variable's repr(), not a python object.
160 'user_variables' : list,
160 'user_variables' : list,
161
161
162 # Similarly, a dict mapping names to expressions to be evaluated in the
162 # Similarly, a dict mapping names to expressions to be evaluated in the
163 # user's dict.
163 # user's dict.
164 'user_expressions' : dict,
164 'user_expressions' : dict,
165
165
166 # Some frontends (e.g. the Notebook) do not support stdin requests. If
166 # Some frontends (e.g. the Notebook) do not support stdin requests. If
167 # raw_input is called from code executed from such a frontend, a
167 # raw_input is called from code executed from such a frontend, a
168 # StdinNotImplementedError will be raised.
168 # StdinNotImplementedError will be raised.
169 'allow_stdin' : True,
169 'allow_stdin' : True,
170
170
171 }
171 }
172
172
173 The ``code`` field contains a single string (possibly multiline). The kernel
173 The ``code`` field contains a single string (possibly multiline). The kernel
174 is responsible for splitting this into one or more independent execution blocks
174 is responsible for splitting this into one or more independent execution blocks
175 and deciding whether to compile these in 'single' or 'exec' mode (see below for
175 and deciding whether to compile these in 'single' or 'exec' mode (see below for
176 detailed execution semantics).
176 detailed execution semantics).
177
177
178 The ``user_`` fields deserve a detailed explanation. In the past, IPython had
178 The ``user_`` fields deserve a detailed explanation. In the past, IPython had
179 the notion of a prompt string that allowed arbitrary code to be evaluated, and
179 the notion of a prompt string that allowed arbitrary code to be evaluated, and
180 this was put to good use by many in creating prompts that displayed system
180 this was put to good use by many in creating prompts that displayed system
181 status, path information, and even more esoteric uses like remote instrument
181 status, path information, and even more esoteric uses like remote instrument
182 status aqcuired over the network. But now that IPython has a clean separation
182 status aqcuired over the network. But now that IPython has a clean separation
183 between the kernel and the clients, the kernel has no prompt knowledge; prompts
183 between the kernel and the clients, the kernel has no prompt knowledge; prompts
184 are a frontend-side feature, and it should be even possible for different
184 are a frontend-side feature, and it should be even possible for different
185 frontends to display different prompts while interacting with the same kernel.
185 frontends to display different prompts while interacting with the same kernel.
186
186
187 The kernel now provides the ability to retrieve data from the user's namespace
187 The kernel now provides the ability to retrieve data from the user's namespace
188 after the execution of the main ``code``, thanks to two fields in the
188 after the execution of the main ``code``, thanks to two fields in the
189 ``execute_request`` message:
189 ``execute_request`` message:
190
190
191 - ``user_variables``: If only variables from the user's namespace are needed, a
191 - ``user_variables``: If only variables from the user's namespace are needed, a
192 list of variable names can be passed and a dict with these names as keys and
192 list of variable names can be passed and a dict with these names as keys and
193 their :func:`repr()` as values will be returned.
193 their :func:`repr()` as values will be returned.
194
194
195 - ``user_expressions``: For more complex expressions that require function
195 - ``user_expressions``: For more complex expressions that require function
196 evaluations, a dict can be provided with string keys and arbitrary python
196 evaluations, a dict can be provided with string keys and arbitrary python
197 expressions as values. The return message will contain also a dict with the
197 expressions as values. The return message will contain also a dict with the
198 same keys and the :func:`repr()` of the evaluated expressions as value.
198 same keys and the :func:`repr()` of the evaluated expressions as value.
199
199
200 With this information, frontends can display any status information they wish
200 With this information, frontends can display any status information they wish
201 in the form that best suits each frontend (a status line, a popup, inline for a
201 in the form that best suits each frontend (a status line, a popup, inline for a
202 terminal, etc).
202 terminal, etc).
203
203
204 .. Note::
204 .. Note::
205
205
206 In order to obtain the current execution counter for the purposes of
206 In order to obtain the current execution counter for the purposes of
207 displaying input prompts, frontends simply make an execution request with an
207 displaying input prompts, frontends simply make an execution request with an
208 empty code string and ``silent=True``.
208 empty code string and ``silent=True``.
209
209
210 Execution semantics
210 Execution semantics
211 ~~~~~~~~~~~~~~~~~~~
211 ~~~~~~~~~~~~~~~~~~~
212
212
213 When the silent flag is false, the execution of use code consists of the
213 When the silent flag is false, the execution of use code consists of the
214 following phases (in silent mode, only the ``code`` field is executed):
214 following phases (in silent mode, only the ``code`` field is executed):
215
215
216 1. Run the ``pre_runcode_hook``.
216 1. Run the ``pre_runcode_hook``.
217
217
218 2. Execute the ``code`` field, see below for details.
218 2. Execute the ``code`` field, see below for details.
219
219
220 3. If #2 succeeds, compute ``user_variables`` and ``user_expressions`` are
220 3. If #2 succeeds, compute ``user_variables`` and ``user_expressions`` are
221 computed. This ensures that any error in the latter don't harm the main
221 computed. This ensures that any error in the latter don't harm the main
222 code execution.
222 code execution.
223
223
224 4. Call any method registered with :meth:`register_post_execute`.
224 4. Call any method registered with :meth:`register_post_execute`.
225
225
226 .. warning::
226 .. warning::
227
227
228 The API for running code before/after the main code block is likely to
228 The API for running code before/after the main code block is likely to
229 change soon. Both the ``pre_runcode_hook`` and the
229 change soon. Both the ``pre_runcode_hook`` and the
230 :meth:`register_post_execute` are susceptible to modification, as we find a
230 :meth:`register_post_execute` are susceptible to modification, as we find a
231 consistent model for both.
231 consistent model for both.
232
232
233 To understand how the ``code`` field is executed, one must know that Python
233 To understand how the ``code`` field is executed, one must know that Python
234 code can be compiled in one of three modes (controlled by the ``mode`` argument
234 code can be compiled in one of three modes (controlled by the ``mode`` argument
235 to the :func:`compile` builtin):
235 to the :func:`compile` builtin):
236
236
237 *single*
237 *single*
238 Valid for a single interactive statement (though the source can contain
238 Valid for a single interactive statement (though the source can contain
239 multiple lines, such as a for loop). When compiled in this mode, the
239 multiple lines, such as a for loop). When compiled in this mode, the
240 generated bytecode contains special instructions that trigger the calling of
240 generated bytecode contains special instructions that trigger the calling of
241 :func:`sys.displayhook` for any expression in the block that returns a value.
241 :func:`sys.displayhook` for any expression in the block that returns a value.
242 This means that a single statement can actually produce multiple calls to
242 This means that a single statement can actually produce multiple calls to
243 :func:`sys.displayhook`, if for example it contains a loop where each
243 :func:`sys.displayhook`, if for example it contains a loop where each
244 iteration computes an unassigned expression would generate 10 calls::
244 iteration computes an unassigned expression would generate 10 calls::
245
245
246 for i in range(10):
246 for i in range(10):
247 i**2
247 i**2
248
248
249 *exec*
249 *exec*
250 An arbitrary amount of source code, this is how modules are compiled.
250 An arbitrary amount of source code, this is how modules are compiled.
251 :func:`sys.displayhook` is *never* implicitly called.
251 :func:`sys.displayhook` is *never* implicitly called.
252
252
253 *eval*
253 *eval*
254 A single expression that returns a value. :func:`sys.displayhook` is *never*
254 A single expression that returns a value. :func:`sys.displayhook` is *never*
255 implicitly called.
255 implicitly called.
256
256
257
257
258 The ``code`` field is split into individual blocks each of which is valid for
258 The ``code`` field is split into individual blocks each of which is valid for
259 execution in 'single' mode, and then:
259 execution in 'single' mode, and then:
260
260
261 - If there is only a single block: it is executed in 'single' mode.
261 - If there is only a single block: it is executed in 'single' mode.
262
262
263 - If there is more than one block:
263 - If there is more than one block:
264
264
265 * if the last one is a single line long, run all but the last in 'exec' mode
265 * if the last one is a single line long, run all but the last in 'exec' mode
266 and the very last one in 'single' mode. This makes it easy to type simple
266 and the very last one in 'single' mode. This makes it easy to type simple
267 expressions at the end to see computed values.
267 expressions at the end to see computed values.
268
268
269 * if the last one is no more than two lines long, run all but the last in
269 * if the last one is no more than two lines long, run all but the last in
270 'exec' mode and the very last one in 'single' mode. This makes it easy to
270 'exec' mode and the very last one in 'single' mode. This makes it easy to
271 type simple expressions at the end to see computed values. - otherwise
271 type simple expressions at the end to see computed values. - otherwise
272 (last one is also multiline), run all in 'exec' mode
272 (last one is also multiline), run all in 'exec' mode
273
273
274 * otherwise (last one is also multiline), run all in 'exec' mode as a single
274 * otherwise (last one is also multiline), run all in 'exec' mode as a single
275 unit.
275 unit.
276
276
277 Any error in retrieving the ``user_variables`` or evaluating the
277 Any error in retrieving the ``user_variables`` or evaluating the
278 ``user_expressions`` will result in a simple error message in the return fields
278 ``user_expressions`` will result in a simple error message in the return fields
279 of the form::
279 of the form::
280
280
281 [ERROR] ExceptionType: Exception message
281 [ERROR] ExceptionType: Exception message
282
282
283 The user can simply send the same variable name or expression for evaluation to
283 The user can simply send the same variable name or expression for evaluation to
284 see a regular traceback.
284 see a regular traceback.
285
285
286 Errors in any registered post_execute functions are also reported similarly,
286 Errors in any registered post_execute functions are also reported similarly,
287 and the failing function is removed from the post_execution set so that it does
287 and the failing function is removed from the post_execution set so that it does
288 not continue triggering failures.
288 not continue triggering failures.
289
289
290 Upon completion of the execution request, the kernel *always* sends a reply,
290 Upon completion of the execution request, the kernel *always* sends a reply,
291 with a status code indicating what happened and additional data depending on
291 with a status code indicating what happened and additional data depending on
292 the outcome. See :ref:`below <execution_results>` for the possible return
292 the outcome. See :ref:`below <execution_results>` for the possible return
293 codes and associated data.
293 codes and associated data.
294
294
295
295
296 Execution counter (old prompt number)
296 Execution counter (old prompt number)
297 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
297 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
298
298
299 The kernel has a single, monotonically increasing counter of all execution
299 The kernel has a single, monotonically increasing counter of all execution
300 requests that are made with ``silent=False``. This counter is used to populate
300 requests that are made with ``silent=False``. This counter is used to populate
301 the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will likely want to
301 the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will likely want to
302 display it in some form to the user, which will typically (but not necessarily)
302 display it in some form to the user, which will typically (but not necessarily)
303 be done in the prompts. The value of this counter will be returned as the
303 be done in the prompts. The value of this counter will be returned as the
304 ``execution_count`` field of all ``execute_reply`` messages.
304 ``execution_count`` field of all ``execute_reply`` messages.
305
305
306 .. _execution_results:
306 .. _execution_results:
307
307
308 Execution results
308 Execution results
309 ~~~~~~~~~~~~~~~~~
309 ~~~~~~~~~~~~~~~~~
310
310
311 Message type: ``execute_reply``::
311 Message type: ``execute_reply``::
312
312
313 content = {
313 content = {
314 # One of: 'ok' OR 'error' OR 'abort'
314 # One of: 'ok' OR 'error' OR 'abort'
315 'status' : str,
315 'status' : str,
316
316
317 # The global kernel counter that increases by one with each non-silent
317 # The global kernel counter that increases by one with each non-silent
318 # executed request. This will typically be used by clients to display
318 # executed request. This will typically be used by clients to display
319 # prompt numbers to the user. If the request was a silent one, this will
319 # prompt numbers to the user. If the request was a silent one, this will
320 # be the current value of the counter in the kernel.
320 # be the current value of the counter in the kernel.
321 'execution_count' : int,
321 'execution_count' : int,
322 }
322 }
323
323
324 When status is 'ok', the following extra fields are present::
324 When status is 'ok', the following extra fields are present::
325
325
326 {
326 {
327 # The execution payload is a dict with string keys that may have been
327 # The execution payload is a dict with string keys that may have been
328 # produced by the code being executed. It is retrieved by the kernel at
328 # produced by the code being executed. It is retrieved by the kernel at
329 # the end of the execution and sent back to the front end, which can take
329 # the end of the execution and sent back to the front end, which can take
330 # action on it as needed. See main text for further details.
330 # action on it as needed. See main text for further details.
331 'payload' : dict,
331 'payload' : dict,
332
332
333 # Results for the user_variables and user_expressions.
333 # Results for the user_variables and user_expressions.
334 'user_variables' : dict,
334 'user_variables' : dict,
335 'user_expressions' : dict,
335 'user_expressions' : dict,
336
336
337 # The kernel will often transform the input provided to it. If the
337 # The kernel will often transform the input provided to it. If the
338 # '---->' transform had been applied, this is filled, otherwise it's the
338 # '---->' transform had been applied, this is filled, otherwise it's the
339 # empty string. So transformations like magics don't appear here, only
339 # empty string. So transformations like magics don't appear here, only
340 # autocall ones.
340 # autocall ones.
341 'transformed_code' : str,
341 'transformed_code' : str,
342 }
342 }
343
343
344 .. admonition:: Execution payloads
344 .. admonition:: Execution payloads
345
345
346 The notion of an 'execution payload' is different from a return value of a
346 The notion of an 'execution payload' is different from a return value of a
347 given set of code, which normally is just displayed on the pyout stream
347 given set of code, which normally is just displayed on the pyout stream
348 through the PUB socket. The idea of a payload is to allow special types of
348 through the PUB socket. The idea of a payload is to allow special types of
349 code, typically magics, to populate a data container in the IPython kernel
349 code, typically magics, to populate a data container in the IPython kernel
350 that will be shipped back to the caller via this channel. The kernel will
350 that will be shipped back to the caller via this channel. The kernel will
351 have an API for this, probably something along the lines of::
351 have an API for this, probably something along the lines of::
352
352
353 ip.exec_payload_add(key, value)
353 ip.exec_payload_add(key, value)
354
354
355 though this API is still in the design stages. The data returned in this
355 though this API is still in the design stages. The data returned in this
356 payload will allow frontends to present special views of what just happened.
356 payload will allow frontends to present special views of what just happened.
357
357
358
358
359 When status is 'error', the following extra fields are present::
359 When status is 'error', the following extra fields are present::
360
360
361 {
361 {
362 'exc_name' : str, # Exception name, as a string
362 'exc_name' : str, # Exception name, as a string
363 'exc_value' : str, # Exception value, as a string
363 'exc_value' : str, # Exception value, as a string
364
364
365 # The traceback will contain a list of frames, represented each as a
365 # The traceback will contain a list of frames, represented each as a
366 # string. For now we'll stick to the existing design of ultraTB, which
366 # string. For now we'll stick to the existing design of ultraTB, which
367 # controls exception level of detail statefully. But eventually we'll
367 # controls exception level of detail statefully. But eventually we'll
368 # want to grow into a model where more information is collected and
368 # want to grow into a model where more information is collected and
369 # packed into the traceback object, with clients deciding how little or
369 # packed into the traceback object, with clients deciding how little or
370 # how much of it to unpack. But for now, let's start with a simple list
370 # how much of it to unpack. But for now, let's start with a simple list
371 # of strings, since that requires only minimal changes to ultratb as
371 # of strings, since that requires only minimal changes to ultratb as
372 # written.
372 # written.
373 'traceback' : list,
373 'traceback' : list,
374 }
374 }
375
375
376
376
377 When status is 'abort', there are for now no additional data fields. This
377 When status is 'abort', there are for now no additional data fields. This
378 happens when the kernel was interrupted by a signal.
378 happens when the kernel was interrupted by a signal.
379
379
380 Kernel attribute access
380 Kernel attribute access
381 -----------------------
381 -----------------------
382
382
383 .. warning::
383 .. warning::
384
384
385 This part of the messaging spec is not actually implemented in the kernel
385 This part of the messaging spec is not actually implemented in the kernel
386 yet.
386 yet.
387
387
388 While this protocol does not specify full RPC access to arbitrary methods of
388 While this protocol does not specify full RPC access to arbitrary methods of
389 the kernel object, the kernel does allow read (and in some cases write) access
389 the kernel object, the kernel does allow read (and in some cases write) access
390 to certain attributes.
390 to certain attributes.
391
391
392 The policy for which attributes can be read is: any attribute of the kernel, or
392 The policy for which attributes can be read is: any attribute of the kernel, or
393 its sub-objects, that belongs to a :class:`Configurable` object and has been
393 its sub-objects, that belongs to a :class:`Configurable` object and has been
394 declared at the class-level with Traits validation, is in principle accessible
394 declared at the class-level with Traits validation, is in principle accessible
395 as long as its name does not begin with a leading underscore. The attribute
395 as long as its name does not begin with a leading underscore. The attribute
396 itself will have metadata indicating whether it allows remote read and/or write
396 itself will have metadata indicating whether it allows remote read and/or write
397 access. The message spec follows for attribute read and write requests.
397 access. The message spec follows for attribute read and write requests.
398
398
399 Message type: ``getattr_request``::
399 Message type: ``getattr_request``::
400
400
401 content = {
401 content = {
402 # The (possibly dotted) name of the attribute
402 # The (possibly dotted) name of the attribute
403 'name' : str,
403 'name' : str,
404 }
404 }
405
405
406 When a ``getattr_request`` fails, there are two possible error types:
406 When a ``getattr_request`` fails, there are two possible error types:
407
407
408 - AttributeError: this type of error was raised when trying to access the
408 - AttributeError: this type of error was raised when trying to access the
409 given name by the kernel itself. This means that the attribute likely
409 given name by the kernel itself. This means that the attribute likely
410 doesn't exist.
410 doesn't exist.
411
411
412 - AccessError: the attribute exists but its value is not readable remotely.
412 - AccessError: the attribute exists but its value is not readable remotely.
413
413
414
414
415 Message type: ``getattr_reply``::
415 Message type: ``getattr_reply``::
416
416
417 content = {
417 content = {
418 # One of ['ok', 'AttributeError', 'AccessError'].
418 # One of ['ok', 'AttributeError', 'AccessError'].
419 'status' : str,
419 'status' : str,
420 # If status is 'ok', a JSON object.
420 # If status is 'ok', a JSON object.
421 'value' : object,
421 'value' : object,
422 }
422 }
423
423
424 Message type: ``setattr_request``::
424 Message type: ``setattr_request``::
425
425
426 content = {
426 content = {
427 # The (possibly dotted) name of the attribute
427 # The (possibly dotted) name of the attribute
428 'name' : str,
428 'name' : str,
429
429
430 # A JSON-encoded object, that will be validated by the Traits
430 # A JSON-encoded object, that will be validated by the Traits
431 # information in the kernel
431 # information in the kernel
432 'value' : object,
432 'value' : object,
433 }
433 }
434
434
435 When a ``setattr_request`` fails, there are also two possible error types with
435 When a ``setattr_request`` fails, there are also two possible error types with
436 similar meanings as those of the ``getattr_request`` case, but for writing.
436 similar meanings as those of the ``getattr_request`` case, but for writing.
437
437
438 Message type: ``setattr_reply``::
438 Message type: ``setattr_reply``::
439
439
440 content = {
440 content = {
441 # One of ['ok', 'AttributeError', 'AccessError'].
441 # One of ['ok', 'AttributeError', 'AccessError'].
442 'status' : str,
442 'status' : str,
443 }
443 }
444
444
445
445
446
446
447 Object information
447 Object information
448 ------------------
448 ------------------
449
449
450 One of IPython's most used capabilities is the introspection of Python objects
450 One of IPython's most used capabilities is the introspection of Python objects
451 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
451 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
452 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
452 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
453 enough that it warrants an explicit message type, especially because frontends
453 enough that it warrants an explicit message type, especially because frontends
454 may want to get object information in response to user keystrokes (like Tab or
454 may want to get object information in response to user keystrokes (like Tab or
455 F1) besides from the user explicitly typing code like ``x??``.
455 F1) besides from the user explicitly typing code like ``x??``.
456
456
457 Message type: ``object_info_request``::
457 Message type: ``object_info_request``::
458
458
459 content = {
459 content = {
460 # The (possibly dotted) name of the object to be searched in all
460 # The (possibly dotted) name of the object to be searched in all
461 # relevant namespaces
461 # relevant namespaces
462 'name' : str,
462 'name' : str,
463
463
464 # The level of detail desired. The default (0) is equivalent to typing
464 # The level of detail desired. The default (0) is equivalent to typing
465 # 'x?' at the prompt, 1 is equivalent to 'x??'.
465 # 'x?' at the prompt, 1 is equivalent to 'x??'.
466 'detail_level' : int,
466 'detail_level' : int,
467 }
467 }
468
468
469 The returned information will be a dictionary with keys very similar to the
469 The returned information will be a dictionary with keys very similar to the
470 field names that IPython prints at the terminal.
470 field names that IPython prints at the terminal.
471
471
472 Message type: ``object_info_reply``::
472 Message type: ``object_info_reply``::
473
473
474 content = {
474 content = {
475 # The name the object was requested under
475 # The name the object was requested under
476 'name' : str,
476 'name' : str,
477
477
478 # Boolean flag indicating whether the named object was found or not. If
478 # Boolean flag indicating whether the named object was found or not. If
479 # it's false, all other fields will be empty.
479 # it's false, all other fields will be empty.
480 'found' : bool,
480 'found' : bool,
481
481
482 # Flags for magics and system aliases
482 # Flags for magics and system aliases
483 'ismagic' : bool,
483 'ismagic' : bool,
484 'isalias' : bool,
484 'isalias' : bool,
485
485
486 # The name of the namespace where the object was found ('builtin',
486 # The name of the namespace where the object was found ('builtin',
487 # 'magics', 'alias', 'interactive', etc.)
487 # 'magics', 'alias', 'interactive', etc.)
488 'namespace' : str,
488 'namespace' : str,
489
489
490 # The type name will be type.__name__ for normal Python objects, but it
490 # The type name will be type.__name__ for normal Python objects, but it
491 # can also be a string like 'Magic function' or 'System alias'
491 # can also be a string like 'Magic function' or 'System alias'
492 'type_name' : str,
492 'type_name' : str,
493
493
494 # The string form of the object, possibly truncated for length if
494 # The string form of the object, possibly truncated for length if
495 # detail_level is 0
495 # detail_level is 0
496 'string_form' : str,
496 'string_form' : str,
497
497
498 # For objects with a __class__ attribute this will be set
498 # For objects with a __class__ attribute this will be set
499 'base_class' : str,
499 'base_class' : str,
500
500
501 # For objects with a __len__ attribute this will be set
501 # For objects with a __len__ attribute this will be set
502 'length' : int,
502 'length' : int,
503
503
504 # If the object is a function, class or method whose file we can find,
504 # If the object is a function, class or method whose file we can find,
505 # we give its full path
505 # we give its full path
506 'file' : str,
506 'file' : str,
507
507
508 # For pure Python callable objects, we can reconstruct the object
508 # For pure Python callable objects, we can reconstruct the object
509 # definition line which provides its call signature. For convenience this
509 # definition line which provides its call signature. For convenience this
510 # is returned as a single 'definition' field, but below the raw parts that
510 # is returned as a single 'definition' field, but below the raw parts that
511 # compose it are also returned as the argspec field.
511 # compose it are also returned as the argspec field.
512 'definition' : str,
512 'definition' : str,
513
513
514 # The individual parts that together form the definition string. Clients
514 # The individual parts that together form the definition string. Clients
515 # with rich display capabilities may use this to provide a richer and more
515 # with rich display capabilities may use this to provide a richer and more
516 # precise representation of the definition line (e.g. by highlighting
516 # precise representation of the definition line (e.g. by highlighting
517 # arguments based on the user's cursor position). For non-callable
517 # arguments based on the user's cursor position). For non-callable
518 # objects, this field is empty.
518 # objects, this field is empty.
519 'argspec' : { # The names of all the arguments
519 'argspec' : { # The names of all the arguments
520 args : list,
520 args : list,
521 # The name of the varargs (*args), if any
521 # The name of the varargs (*args), if any
522 varargs : str,
522 varargs : str,
523 # The name of the varkw (**kw), if any
523 # The name of the varkw (**kw), if any
524 varkw : str,
524 varkw : str,
525 # The values (as strings) of all default arguments. Note
525 # The values (as strings) of all default arguments. Note
526 # that these must be matched *in reverse* with the 'args'
526 # that these must be matched *in reverse* with the 'args'
527 # list above, since the first positional args have no default
527 # list above, since the first positional args have no default
528 # value at all.
528 # value at all.
529 defaults : list,
529 defaults : list,
530 },
530 },
531
531
532 # For instances, provide the constructor signature (the definition of
532 # For instances, provide the constructor signature (the definition of
533 # the __init__ method):
533 # the __init__ method):
534 'init_definition' : str,
534 'init_definition' : str,
535
535
536 # Docstrings: for any object (function, method, module, package) with a
536 # Docstrings: for any object (function, method, module, package) with a
537 # docstring, we show it. But in addition, we may provide additional
537 # docstring, we show it. But in addition, we may provide additional
538 # docstrings. For example, for instances we will show the constructor
538 # docstrings. For example, for instances we will show the constructor
539 # and class docstrings as well, if available.
539 # and class docstrings as well, if available.
540 'docstring' : str,
540 'docstring' : str,
541
541
542 # For instances, provide the constructor and class docstrings
542 # For instances, provide the constructor and class docstrings
543 'init_docstring' : str,
543 'init_docstring' : str,
544 'class_docstring' : str,
544 'class_docstring' : str,
545
545
546 # If it's a callable object whose call method has a separate docstring and
546 # If it's a callable object whose call method has a separate docstring and
547 # definition line:
547 # definition line:
548 'call_def' : str,
548 'call_def' : str,
549 'call_docstring' : str,
549 'call_docstring' : str,
550
550
551 # If detail_level was 1, we also try to find the source code that
551 # If detail_level was 1, we also try to find the source code that
552 # defines the object, if possible. The string 'None' will indicate
552 # defines the object, if possible. The string 'None' will indicate
553 # that no source was found.
553 # that no source was found.
554 'source' : str,
554 'source' : str,
555 }
555 }
556 '
556 '
557
557
558 Complete
558 Complete
559 --------
559 --------
560
560
561 Message type: ``complete_request``::
561 Message type: ``complete_request``::
562
562
563 content = {
563 content = {
564 # The text to be completed, such as 'a.is'
564 # The text to be completed, such as 'a.is'
565 'text' : str,
565 'text' : str,
566
566
567 # The full line, such as 'print a.is'. This allows completers to
567 # The full line, such as 'print a.is'. This allows completers to
568 # make decisions that may require information about more than just the
568 # make decisions that may require information about more than just the
569 # current word.
569 # current word.
570 'line' : str,
570 'line' : str,
571
571
572 # The entire block of text where the line is. This may be useful in the
572 # The entire block of text where the line is. This may be useful in the
573 # case of multiline completions where more context may be needed. Note: if
573 # case of multiline completions where more context may be needed. Note: if
574 # in practice this field proves unnecessary, remove it to lighten the
574 # in practice this field proves unnecessary, remove it to lighten the
575 # messages.
575 # messages.
576
576
577 'block' : str,
577 'block' : str,
578
578
579 # The position of the cursor where the user hit 'TAB' on the line.
579 # The position of the cursor where the user hit 'TAB' on the line.
580 'cursor_pos' : int,
580 'cursor_pos' : int,
581 }
581 }
582
582
583 Message type: ``complete_reply``::
583 Message type: ``complete_reply``::
584
584
585 content = {
585 content = {
586 # The list of all matches to the completion request, such as
586 # The list of all matches to the completion request, such as
587 # ['a.isalnum', 'a.isalpha'] for the above example.
587 # ['a.isalnum', 'a.isalpha'] for the above example.
588 'matches' : list
588 'matches' : list
589 }
589 }
590
590
591
591
592 History
592 History
593 -------
593 -------
594
594
595 For clients to explicitly request history from a kernel. The kernel has all
595 For clients to explicitly request history from a kernel. The kernel has all
596 the actual execution history stored in a single location, so clients can
596 the actual execution history stored in a single location, so clients can
597 request it from the kernel when needed.
597 request it from the kernel when needed.
598
598
599 Message type: ``history_request``::
599 Message type: ``history_request``::
600
600
601 content = {
601 content = {
602
602
603 # If True, also return output history in the resulting dict.
603 # If True, also return output history in the resulting dict.
604 'output' : bool,
604 'output' : bool,
605
605
606 # If True, return the raw input history, else the transformed input.
606 # If True, return the raw input history, else the transformed input.
607 'raw' : bool,
607 'raw' : bool,
608
608
609 # So far, this can be 'range', 'tail' or 'search'.
609 # So far, this can be 'range', 'tail' or 'search'.
610 'hist_access_type' : str,
610 'hist_access_type' : str,
611
611
612 # If hist_access_type is 'range', get a range of input cells. session can
612 # If hist_access_type is 'range', get a range of input cells. session can
613 # be a positive session number, or a negative number to count back from
613 # be a positive session number, or a negative number to count back from
614 # the current session.
614 # the current session.
615 'session' : int,
615 'session' : int,
616 # start and stop are line numbers within that session.
616 # start and stop are line numbers within that session.
617 'start' : int,
617 'start' : int,
618 'stop' : int,
618 'stop' : int,
619
619
620 # If hist_access_type is 'tail', get the last n cells.
620 # If hist_access_type is 'tail', get the last n cells.
621 'n' : int,
621 'n' : int,
622
622
623 # If hist_access_type is 'search', get cells matching the specified glob
623 # If hist_access_type is 'search', get cells matching the specified glob
624 # pattern (with * and ? as wildcards).
624 # pattern (with * and ? as wildcards).
625 'pattern' : str,
625 'pattern' : str,
626
626
627 }
627 }
628
628
629 Message type: ``history_reply``::
629 Message type: ``history_reply``::
630
630
631 content = {
631 content = {
632 # A list of 3 tuples, either:
632 # A list of 3 tuples, either:
633 # (session, line_number, input) or
633 # (session, line_number, input) or
634 # (session, line_number, (input, output)),
634 # (session, line_number, (input, output)),
635 # depending on whether output was False or True, respectively.
635 # depending on whether output was False or True, respectively.
636 'history' : list,
636 'history' : list,
637 }
637 }
638
638
639
639
640 Connect
640 Connect
641 -------
641 -------
642
642
643 When a client connects to the request/reply socket of the kernel, it can issue
643 When a client connects to the request/reply socket of the kernel, it can issue
644 a connect request to get basic information about the kernel, such as the ports
644 a connect request to get basic information about the kernel, such as the ports
645 the other ZeroMQ sockets are listening on. This allows clients to only have
645 the other ZeroMQ sockets are listening on. This allows clients to only have
646 to know about a single port (the shell channel) to connect to a kernel.
646 to know about a single port (the shell channel) to connect to a kernel.
647
647
648 Message type: ``connect_request``::
648 Message type: ``connect_request``::
649
649
650 content = {
650 content = {
651 }
651 }
652
652
653 Message type: ``connect_reply``::
653 Message type: ``connect_reply``::
654
654
655 content = {
655 content = {
656 'shell_port' : int # The port the shell ROUTER socket is listening on.
656 'shell_port' : int # The port the shell ROUTER socket is listening on.
657 'iopub_port' : int # The port the PUB socket is listening on.
657 'iopub_port' : int # The port the PUB socket is listening on.
658 'stdin_port' : int # The port the stdin ROUTER socket is listening on.
658 'stdin_port' : int # The port the stdin ROUTER socket is listening on.
659 'hb_port' : int # The port the heartbeat socket is listening on.
659 'hb_port' : int # The port the heartbeat socket is listening on.
660 }
660 }
661
661
662
662
663
663
664 Kernel shutdown
664 Kernel shutdown
665 ---------------
665 ---------------
666
666
667 The clients can request the kernel to shut itself down; this is used in
667 The clients can request the kernel to shut itself down; this is used in
668 multiple cases:
668 multiple cases:
669
669
670 - when the user chooses to close the client application via a menu or window
670 - when the user chooses to close the client application via a menu or window
671 control.
671 control.
672 - when the user types 'exit' or 'quit' (or their uppercase magic equivalents).
672 - when the user types 'exit' or 'quit' (or their uppercase magic equivalents).
673 - when the user chooses a GUI method (like the 'Ctrl-C' shortcut in the
673 - when the user chooses a GUI method (like the 'Ctrl-C' shortcut in the
674 IPythonQt client) to force a kernel restart to get a clean kernel without
674 IPythonQt client) to force a kernel restart to get a clean kernel without
675 losing client-side state like history or inlined figures.
675 losing client-side state like history or inlined figures.
676
676
677 The client sends a shutdown request to the kernel, and once it receives the
677 The client sends a shutdown request to the kernel, and once it receives the
678 reply message (which is otherwise empty), it can assume that the kernel has
678 reply message (which is otherwise empty), it can assume that the kernel has
679 completed shutdown safely.
679 completed shutdown safely.
680
680
681 Upon their own shutdown, client applications will typically execute a last
681 Upon their own shutdown, client applications will typically execute a last
682 minute sanity check and forcefully terminate any kernel that is still alive, to
682 minute sanity check and forcefully terminate any kernel that is still alive, to
683 avoid leaving stray processes in the user's machine.
683 avoid leaving stray processes in the user's machine.
684
684
685 For both shutdown request and reply, there is no actual content that needs to
685 For both shutdown request and reply, there is no actual content that needs to
686 be sent, so the content dict is empty.
686 be sent, so the content dict is empty.
687
687
688 Message type: ``shutdown_request``::
688 Message type: ``shutdown_request``::
689
689
690 content = {
690 content = {
691 'restart' : bool # whether the shutdown is final, or precedes a restart
691 'restart' : bool # whether the shutdown is final, or precedes a restart
692 }
692 }
693
693
694 Message type: ``shutdown_reply``::
694 Message type: ``shutdown_reply``::
695
695
696 content = {
696 content = {
697 'restart' : bool # whether the shutdown is final, or precedes a restart
697 'restart' : bool # whether the shutdown is final, or precedes a restart
698 }
698 }
699
699
700 .. Note::
700 .. Note::
701
701
702 When the clients detect a dead kernel thanks to inactivity on the heartbeat
702 When the clients detect a dead kernel thanks to inactivity on the heartbeat
703 socket, they simply send a forceful process termination signal, since a dead
703 socket, they simply send a forceful process termination signal, since a dead
704 process is unlikely to respond in any useful way to messages.
704 process is unlikely to respond in any useful way to messages.
705
705
706
706
707 Messages on the PUB/SUB socket
707 Messages on the PUB/SUB socket
708 ==============================
708 ==============================
709
709
710 Streams (stdout, stderr, etc)
710 Streams (stdout, stderr, etc)
711 ------------------------------
711 ------------------------------
712
712
713 Message type: ``stream``::
713 Message type: ``stream``::
714
714
715 content = {
715 content = {
716 # The name of the stream is one of 'stdin', 'stdout', 'stderr'
716 # The name of the stream is one of 'stdin', 'stdout', 'stderr'
717 'name' : str,
717 'name' : str,
718
718
719 # The data is an arbitrary string to be written to that stream
719 # The data is an arbitrary string to be written to that stream
720 'data' : str,
720 'data' : str,
721 }
721 }
722
722
723 When a kernel receives a raw_input call, it should also broadcast it on the pub
723 When a kernel receives a raw_input call, it should also broadcast it on the pub
724 socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
724 socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
725 to monitor/display kernel interactions and possibly replay them to their user
725 to monitor/display kernel interactions and possibly replay them to their user
726 or otherwise expose them.
726 or otherwise expose them.
727
727
728 Display Data
728 Display Data
729 ------------
729 ------------
730
730
731 This type of message is used to bring back data that should be diplayed (text,
731 This type of message is used to bring back data that should be diplayed (text,
732 html, svg, etc.) in the frontends. This data is published to all frontends.
732 html, svg, etc.) in the frontends. This data is published to all frontends.
733 Each message can have multiple representations of the data; it is up to the
733 Each message can have multiple representations of the data; it is up to the
734 frontend to decide which to use and how. A single message should contain all
734 frontend to decide which to use and how. A single message should contain all
735 possible representations of the same information. Each representation should
735 possible representations of the same information. Each representation should
736 be a JSON'able data structure, and should be a valid MIME type.
736 be a JSON'able data structure, and should be a valid MIME type.
737
737
738 Some questions remain about this design:
738 Some questions remain about this design:
739
739
740 * Do we use this message type for pyout/displayhook? Probably not, because
740 * Do we use this message type for pyout/displayhook? Probably not, because
741 the displayhook also has to handle the Out prompt display. On the other hand
741 the displayhook also has to handle the Out prompt display. On the other hand
742 we could put that information into the metadata secion.
742 we could put that information into the metadata secion.
743
743
744 Message type: ``display_data``::
744 Message type: ``display_data``::
745
745
746 content = {
746 content = {
747
747
748 # Who create the data
748 # Who create the data
749 'source' : str,
749 'source' : str,
750
750
751 # The data dict contains key/value pairs, where the kids are MIME
751 # The data dict contains key/value pairs, where the kids are MIME
752 # types and the values are the raw data of the representation in that
752 # types and the values are the raw data of the representation in that
753 # format. The data dict must minimally contain the ``text/plain``
753 # format. The data dict must minimally contain the ``text/plain``
754 # MIME type which is used as a backup representation.
754 # MIME type which is used as a backup representation.
755 'data' : dict,
755 'data' : dict,
756
756
757 # Any metadata that describes the data
757 # Any metadata that describes the data
758 'metadata' : dict
758 'metadata' : dict
759 }
759 }
760
760
761 Python inputs
761 Python inputs
762 -------------
762 -------------
763
763
764 These messages are the re-broadcast of the ``execute_request``.
764 These messages are the re-broadcast of the ``execute_request``.
765
765
766 Message type: ``pyin``::
766 Message type: ``pyin``::
767
767
768 content = {
768 content = {
769 'code' : str # Source code to be executed, one or more lines
769 'code' : str, # Source code to be executed, one or more lines
770
771 # The counter for this execution is also provided so that clients can
772 # display it, since IPython automatically creates variables called _iN
773 # (for input prompt In[N]).
774 'execution_count' : int
770 }
775 }
771
776
772 Python outputs
777 Python outputs
773 --------------
778 --------------
774
779
775 When Python produces output from code that has been compiled in with the
780 When Python produces output from code that has been compiled in with the
776 'single' flag to :func:`compile`, any expression that produces a value (such as
781 'single' flag to :func:`compile`, any expression that produces a value (such as
777 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
782 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
778 this value whatever it wants. The default behavior of ``sys.displayhook`` in
783 this value whatever it wants. The default behavior of ``sys.displayhook`` in
779 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
784 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
780 the value as long as it is not ``None`` (which isn't printed at all). In our
785 the value as long as it is not ``None`` (which isn't printed at all). In our
781 case, the kernel instantiates as ``sys.displayhook`` an object which has
786 case, the kernel instantiates as ``sys.displayhook`` an object which has
782 similar behavior, but which instead of printing to stdout, broadcasts these
787 similar behavior, but which instead of printing to stdout, broadcasts these
783 values as ``pyout`` messages for clients to display appropriately.
788 values as ``pyout`` messages for clients to display appropriately.
784
789
785 IPython's displayhook can handle multiple simultaneous formats depending on its
790 IPython's displayhook can handle multiple simultaneous formats depending on its
786 configuration. The default pretty-printed repr text is always given with the
791 configuration. The default pretty-printed repr text is always given with the
787 ``data`` entry in this message. Any other formats are provided in the
792 ``data`` entry in this message. Any other formats are provided in the
788 ``extra_formats`` list. Frontends are free to display any or all of these
793 ``extra_formats`` list. Frontends are free to display any or all of these
789 according to its capabilities. ``extra_formats`` list contains 3-tuples of an ID
794 according to its capabilities. ``extra_formats`` list contains 3-tuples of an ID
790 string, a type string, and the data. The ID is unique to the formatter
795 string, a type string, and the data. The ID is unique to the formatter
791 implementation that created the data. Frontends will typically ignore the ID
796 implementation that created the data. Frontends will typically ignore the ID
792 unless if it has requested a particular formatter. The type string tells the
797 unless if it has requested a particular formatter. The type string tells the
793 frontend how to interpret the data. It is often, but not always a MIME type.
798 frontend how to interpret the data. It is often, but not always a MIME type.
794 Frontends should ignore types that it does not understand. The data itself is
799 Frontends should ignore types that it does not understand. The data itself is
795 any JSON object and depends on the format. It is often, but not always a string.
800 any JSON object and depends on the format. It is often, but not always a string.
796
801
797 Message type: ``pyout``::
802 Message type: ``pyout``::
798
803
799 content = {
804 content = {
800
805
801 # The counter for this execution is also provided so that clients can
806 # The counter for this execution is also provided so that clients can
802 # display it, since IPython automatically creates variables called _N
807 # display it, since IPython automatically creates variables called _N
803 # (for prompt N).
808 # (for prompt N).
804 'execution_count' : int,
809 'execution_count' : int,
805
810
806 # The data dict contains key/value pairs, where the kids are MIME
811 # The data dict contains key/value pairs, where the kids are MIME
807 # types and the values are the raw data of the representation in that
812 # types and the values are the raw data of the representation in that
808 # format. The data dict must minimally contain the ``text/plain``
813 # format. The data dict must minimally contain the ``text/plain``
809 # MIME type which is used as a backup representation.
814 # MIME type which is used as a backup representation.
810 'data' : dict,
815 'data' : dict,
811
816
812 }
817 }
813
818
814 Python errors
819 Python errors
815 -------------
820 -------------
816
821
817 When an error occurs during code execution
822 When an error occurs during code execution
818
823
819 Message type: ``pyerr``::
824 Message type: ``pyerr``::
820
825
821 content = {
826 content = {
822 # Similar content to the execute_reply messages for the 'error' case,
827 # Similar content to the execute_reply messages for the 'error' case,
823 # except the 'status' field is omitted.
828 # except the 'status' field is omitted.
824 }
829 }
825
830
826 Kernel status
831 Kernel status
827 -------------
832 -------------
828
833
829 This message type is used by frontends to monitor the status of the kernel.
834 This message type is used by frontends to monitor the status of the kernel.
830
835
831 Message type: ``status``::
836 Message type: ``status``::
832
837
833 content = {
838 content = {
834 # When the kernel starts to execute code, it will enter the 'busy'
839 # When the kernel starts to execute code, it will enter the 'busy'
835 # state and when it finishes, it will enter the 'idle' state.
840 # state and when it finishes, it will enter the 'idle' state.
836 execution_state : ('busy', 'idle')
841 execution_state : ('busy', 'idle')
837 }
842 }
838
843
839 Kernel crashes
844 Kernel crashes
840 --------------
845 --------------
841
846
842 When the kernel has an unexpected exception, caught by the last-resort
847 When the kernel has an unexpected exception, caught by the last-resort
843 sys.excepthook, we should broadcast the crash handler's output before exiting.
848 sys.excepthook, we should broadcast the crash handler's output before exiting.
844 This will allow clients to notice that a kernel died, inform the user and
849 This will allow clients to notice that a kernel died, inform the user and
845 propose further actions.
850 propose further actions.
846
851
847 Message type: ``crash``::
852 Message type: ``crash``::
848
853
849 content = {
854 content = {
850 # Similarly to the 'error' case for execute_reply messages, this will
855 # Similarly to the 'error' case for execute_reply messages, this will
851 # contain exc_name, exc_type and traceback fields.
856 # contain exc_name, exc_type and traceback fields.
852
857
853 # An additional field with supplementary information such as where to
858 # An additional field with supplementary information such as where to
854 # send the crash message
859 # send the crash message
855 'info' : str,
860 'info' : str,
856 }
861 }
857
862
858
863
859 Future ideas
864 Future ideas
860 ------------
865 ------------
861
866
862 Other potential message types, currently unimplemented, listed below as ideas.
867 Other potential message types, currently unimplemented, listed below as ideas.
863
868
864 Message type: ``file``::
869 Message type: ``file``::
865
870
866 content = {
871 content = {
867 'path' : 'cool.jpg',
872 'path' : 'cool.jpg',
868 'mimetype' : str,
873 'mimetype' : str,
869 'data' : str,
874 'data' : str,
870 }
875 }
871
876
872
877
873 Messages on the stdin ROUTER/DEALER sockets
878 Messages on the stdin ROUTER/DEALER sockets
874 ===========================================
879 ===========================================
875
880
876 This is a socket where the request/reply pattern goes in the opposite direction:
881 This is a socket where the request/reply pattern goes in the opposite direction:
877 from the kernel to a *single* frontend, and its purpose is to allow
882 from the kernel to a *single* frontend, and its purpose is to allow
878 ``raw_input`` and similar operations that read from ``sys.stdin`` on the kernel
883 ``raw_input`` and similar operations that read from ``sys.stdin`` on the kernel
879 to be fulfilled by the client. The request should be made to the frontend that
884 to be fulfilled by the client. The request should be made to the frontend that
880 made the execution request that prompted ``raw_input`` to be called. For now we
885 made the execution request that prompted ``raw_input`` to be called. For now we
881 will keep these messages as simple as possible, since they only mean to convey
886 will keep these messages as simple as possible, since they only mean to convey
882 the ``raw_input(prompt)`` call.
887 the ``raw_input(prompt)`` call.
883
888
884 Message type: ``input_request``::
889 Message type: ``input_request``::
885
890
886 content = { 'prompt' : str }
891 content = { 'prompt' : str }
887
892
888 Message type: ``input_reply``::
893 Message type: ``input_reply``::
889
894
890 content = { 'value' : str }
895 content = { 'value' : str }
891
896
892 .. Note::
897 .. Note::
893
898
894 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
899 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
895 practice the kernel should behave like an interactive program. When a
900 practice the kernel should behave like an interactive program. When a
896 program is opened on the console, the keyboard effectively takes over the
901 program is opened on the console, the keyboard effectively takes over the
897 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
902 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
898 Since the IPython kernel effectively behaves like a console program (albeit
903 Since the IPython kernel effectively behaves like a console program (albeit
899 one whose "keyboard" is actually living in a separate process and
904 one whose "keyboard" is actually living in a separate process and
900 transported over the zmq connection), raw ``stdin`` isn't expected to be
905 transported over the zmq connection), raw ``stdin`` isn't expected to be
901 available.
906 available.
902
907
903
908
904 Heartbeat for kernels
909 Heartbeat for kernels
905 =====================
910 =====================
906
911
907 Initially we had considered using messages like those above over ZMQ for a
912 Initially we had considered using messages like those above over ZMQ for a
908 kernel 'heartbeat' (a way to detect quickly and reliably whether a kernel is
913 kernel 'heartbeat' (a way to detect quickly and reliably whether a kernel is
909 alive at all, even if it may be busy executing user code). But this has the
914 alive at all, even if it may be busy executing user code). But this has the
910 problem that if the kernel is locked inside extension code, it wouldn't execute
915 problem that if the kernel is locked inside extension code, it wouldn't execute
911 the python heartbeat code. But it turns out that we can implement a basic
916 the python heartbeat code. But it turns out that we can implement a basic
912 heartbeat with pure ZMQ, without using any Python messaging at all.
917 heartbeat with pure ZMQ, without using any Python messaging at all.
913
918
914 The monitor sends out a single zmq message (right now, it is a str of the
919 The monitor sends out a single zmq message (right now, it is a str of the
915 monitor's lifetime in seconds), and gets the same message right back, prefixed
920 monitor's lifetime in seconds), and gets the same message right back, prefixed
916 with the zmq identity of the DEALER socket in the heartbeat process. This can be
921 with the zmq identity of the DEALER socket in the heartbeat process. This can be
917 a uuid, or even a full message, but there doesn't seem to be a need for packing
922 a uuid, or even a full message, but there doesn't seem to be a need for packing
918 up a message when the sender and receiver are the exact same Python object.
923 up a message when the sender and receiver are the exact same Python object.
919
924
920 The model is this::
925 The model is this::
921
926
922 monitor.send(str(self.lifetime)) # '1.2345678910'
927 monitor.send(str(self.lifetime)) # '1.2345678910'
923
928
924 and the monitor receives some number of messages of the form::
929 and the monitor receives some number of messages of the form::
925
930
926 ['uuid-abcd-dead-beef', '1.2345678910']
931 ['uuid-abcd-dead-beef', '1.2345678910']
927
932
928 where the first part is the zmq.IDENTITY of the heart's DEALER on the engine, and
933 where the first part is the zmq.IDENTITY of the heart's DEALER on the engine, and
929 the rest is the message sent by the monitor. No Python code ever has any
934 the rest is the message sent by the monitor. No Python code ever has any
930 access to the message between the monitor's send, and the monitor's recv.
935 access to the message between the monitor's send, and the monitor's recv.
931
936
932
937
933 ToDo
938 ToDo
934 ====
939 ====
935
940
936 Missing things include:
941 Missing things include:
937
942
938 * Important: finish thinking through the payload concept and API.
943 * Important: finish thinking through the payload concept and API.
939
944
940 * Important: ensure that we have a good solution for magics like %edit. It's
945 * Important: ensure that we have a good solution for magics like %edit. It's
941 likely that with the payload concept we can build a full solution, but not
946 likely that with the payload concept we can build a full solution, but not
942 100% clear yet.
947 100% clear yet.
943
948
944 * Finishing the details of the heartbeat protocol.
949 * Finishing the details of the heartbeat protocol.
945
950
946 * Signal handling: specify what kind of information kernel should broadcast (or
951 * Signal handling: specify what kind of information kernel should broadcast (or
947 not) when it receives signals.
952 not) when it receives signals.
948
953
949 .. include:: ../links.rst
954 .. include:: ../links.rst
General Comments 0
You need to be logged in to leave comments. Login now