##// END OF EJS Templates
Add note about pure-zmq heartbeat messaging.
Fernando Perez -
Show More
@@ -1,560 +1,579 b''
1 ======================
1 ======================
2 Messaging in IPython
2 Messaging in IPython
3 ======================
3 ======================
4
4
5
5
6 Introduction
6 Introduction
7 ============
7 ============
8
8
9 This document explains the basic communications design and messaging
9 This document explains the basic communications design and messaging
10 specification for how the various IPython objects interact over a network
10 specification for how the various IPython objects interact over a network
11 transport. The current implementation uses the ZeroMQ_ library for messaging
11 transport. The current implementation uses the ZeroMQ_ library for messaging
12 within and between hosts.
12 within and between hosts.
13
13
14 .. Note::
14 .. Note::
15
15
16 This document should be considered the authoritative description of the
16 This document should be considered the authoritative description of the
17 IPython messaging protocol, and all developers are strongly encouraged to
17 IPython messaging protocol, and all developers are strongly encouraged to
18 keep it updated as the implementation evolves, so that we have a single
18 keep it updated as the implementation evolves, so that we have a single
19 common reference for all protocol details.
19 common reference for all protocol details.
20
20
21 The basic design is explained in the following diagram:
21 The basic design is explained in the following diagram:
22
22
23 .. image:: frontend-kernel.png
23 .. image:: frontend-kernel.png
24 :width: 450px
24 :width: 450px
25 :alt: IPython kernel/frontend messaging architecture.
25 :alt: IPython kernel/frontend messaging architecture.
26 :align: center
26 :align: center
27 :target: ../_images/frontend-kernel.png
27 :target: ../_images/frontend-kernel.png
28
28
29 A single kernel can be simultaneously connected to one or more frontends. The
29 A single kernel can be simultaneously connected to one or more frontends. The
30 kernel has three sockets that serve the following functions:
30 kernel has three sockets that serve the following functions:
31
31
32 1. REQ: this socket is connected to a *single* frontend at a time, and it allows
32 1. REQ: this socket is connected to a *single* frontend at a time, and it allows
33 the kernel to request input from a frontend when :func:`raw_input` is called.
33 the kernel to request input from a frontend when :func:`raw_input` is called.
34 The frontend holding the matching REP socket acts as a 'virtual keyboard'
34 The frontend holding the matching REP socket acts as a 'virtual keyboard'
35 for the kernel while this communication is happening (illustrated in the
35 for the kernel while this communication is happening (illustrated in the
36 figure by the black outline around the central keyboard). In practice,
36 figure by the black outline around the central keyboard). In practice,
37 frontends may display such kernel requests using a special input widget or
37 frontends may display such kernel requests using a special input widget or
38 otherwise indicating that the user is to type input for the kernel instead
38 otherwise indicating that the user is to type input for the kernel instead
39 of normal commands in the frontend.
39 of normal commands in the frontend.
40
40
41 2. XREP: this single sockets allows multiple incoming connections from
41 2. XREP: this single sockets allows multiple incoming connections from
42 frontends, and this is the socket where requests for code execution, object
42 frontends, and this is the socket where requests for code execution, object
43 information, prompts, etc. are made to the kernel by any frontend. The
43 information, prompts, etc. are made to the kernel by any frontend. The
44 communication on this socket is a sequence of request/reply actions from
44 communication on this socket is a sequence of request/reply actions from
45 each frontend and the kernel.
45 each frontend and the kernel.
46
46
47 3. PUB: this socket is the 'broadcast channel' where the kernel publishes all
47 3. PUB: this socket is the 'broadcast channel' where the kernel publishes all
48 side effects (stdout, stderr, etc.) as well as the requests coming from any
48 side effects (stdout, stderr, etc.) as well as the requests coming from any
49 client over the XREP socket and its own requests on the REP socket. There
49 client over the XREP socket and its own requests on the REP socket. There
50 are a number of actions in Python which generate side effects: :func:`print`
50 are a number of actions in Python which generate side effects: :func:`print`
51 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
51 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
52 a multi-client scenario, we want all frontends to be able to know what each
52 a multi-client scenario, we want all frontends to be able to know what each
53 other has sent to the kernel (this can be useful in collaborative scenarios,
53 other has sent to the kernel (this can be useful in collaborative scenarios,
54 for example). This socket allows both side effects and the information
54 for example). This socket allows both side effects and the information
55 about communications taking place with one client over the XREQ/XREP channel
55 about communications taking place with one client over the XREQ/XREP channel
56 to be made available to all clients in a uniform manner.
56 to be made available to all clients in a uniform manner.
57
57
58 All messages are tagged with enough information (details below) for clients
58 All messages are tagged with enough information (details below) for clients
59 to know which messages come from their own interaction with the kernel and
59 to know which messages come from their own interaction with the kernel and
60 which ones are from other clients, so they can display each type
60 which ones are from other clients, so they can display each type
61 appropriately.
61 appropriately.
62
62
63 The actual format of the messages allowed on each of these channels is
63 The actual format of the messages allowed on each of these channels is
64 specified below. Messages are dicts of dicts with string keys and values that
64 specified below. Messages are dicts of dicts with string keys and values that
65 are reasonably representable in JSON. Our current implementation uses JSON
65 are reasonably representable in JSON. Our current implementation uses JSON
66 explicitly as its message format, but this shouldn't be considered a permanent
66 explicitly as its message format, but this shouldn't be considered a permanent
67 feature. As we've discovered that JSON has non-trivial performance issues due
67 feature. As we've discovered that JSON has non-trivial performance issues due
68 to excessive copying, we may in the future move to a pure pickle-based raw
68 to excessive copying, we may in the future move to a pure pickle-based raw
69 message format. However, it should be possible to easily convert from the raw
69 message format. However, it should be possible to easily convert from the raw
70 objects to JSON, since we may have non-python clients (e.g. a web frontend).
70 objects to JSON, since we may have non-python clients (e.g. a web frontend).
71 As long as it's easy to make a JSON version of the objects that is a faithful
71 As long as it's easy to make a JSON version of the objects that is a faithful
72 representation of all the data, we can communicate with such clients.
72 representation of all the data, we can communicate with such clients.
73
73
74 .. Note::
74 .. Note::
75
75
76 Not all of these have yet been fully fleshed out, but the key ones are, see
76 Not all of these have yet been fully fleshed out, but the key ones are, see
77 kernel and frontend files for actual implementation details.
77 kernel and frontend files for actual implementation details.
78
78
79
79
80 Python functional API
80 Python functional API
81 =====================
81 =====================
82
82
83 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
83 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
84 should develop, at a few key points, functional forms of all the requests that
84 should develop, at a few key points, functional forms of all the requests that
85 take arguments in this manner and automatically construct the necessary dict
85 take arguments in this manner and automatically construct the necessary dict
86 for sending.
86 for sending.
87
87
88
88
89 General Message Format
89 General Message Format
90 ======================
90 ======================
91
91
92 All messages send or received by any IPython process should have the following
92 All messages send or received by any IPython process should have the following
93 generic structure::
93 generic structure::
94
94
95 {
95 {
96 # The message header contains a pair of unique identifiers for the
96 # The message header contains a pair of unique identifiers for the
97 # originating session and the actual message id, in addition to the
97 # originating session and the actual message id, in addition to the
98 # username for the process that generated the message. This is useful in
98 # username for the process that generated the message. This is useful in
99 # collaborative settings where multiple users may be interacting with the
99 # collaborative settings where multiple users may be interacting with the
100 # same kernel simultaneously, so that frontends can label the various
100 # same kernel simultaneously, so that frontends can label the various
101 # messages in a meaningful way.
101 # messages in a meaningful way.
102 'header' : { 'msg_id' : uuid,
102 'header' : { 'msg_id' : uuid,
103 'username' : str,
103 'username' : str,
104 'session' : uuid
104 'session' : uuid
105 },
105 },
106
106
107 # In a chain of messages, the header from the parent is copied so that
107 # In a chain of messages, the header from the parent is copied so that
108 # clients can track where messages come from.
108 # clients can track where messages come from.
109 'parent_header' : dict,
109 'parent_header' : dict,
110
110
111 # All recognized message type strings are listed below.
111 # All recognized message type strings are listed below.
112 'msg_type' : str,
112 'msg_type' : str,
113
113
114 # The actual content of the message must be a dict, whose structure
114 # The actual content of the message must be a dict, whose structure
115 # depends on the message type.x
115 # depends on the message type.x
116 'content' : dict,
116 'content' : dict,
117 }
117 }
118
118
119 For each message type, the actual content will differ and all existing message
119 For each message type, the actual content will differ and all existing message
120 types are specified in what follows of this document.
120 types are specified in what follows of this document.
121
121
122
122
123 Messages on the XREP/XREQ socket
123 Messages on the XREP/XREQ socket
124 ================================
124 ================================
125
125
126 .. _execute:
126 .. _execute:
127
127
128 Execute
128 Execute
129 -------
129 -------
130
130
131 The execution request contains a single string, but this may be a multiline
131 The execution request contains a single string, but this may be a multiline
132 string. The kernel is responsible for splitting this into possibly more than
132 string. The kernel is responsible for splitting this into possibly more than
133 one block and deciding whether to compile these in 'single' or 'exec' mode.
133 one block and deciding whether to compile these in 'single' or 'exec' mode.
134 We're still sorting out this policy. The current inputsplitter is capable of
134 We're still sorting out this policy. The current inputsplitter is capable of
135 splitting the input for blocks that can all be run as 'single', but in the long
135 splitting the input for blocks that can all be run as 'single', but in the long
136 run it may prove cleaner to only use 'single' mode for truly single-line
136 run it may prove cleaner to only use 'single' mode for truly single-line
137 inputs, and run all multiline input in 'exec' mode. This would preserve the
137 inputs, and run all multiline input in 'exec' mode. This would preserve the
138 natural behavior of single-line inputs while allowing long cells to behave more
138 natural behavior of single-line inputs while allowing long cells to behave more
139 likea a script. This design will be refined as we complete the implementation.
139 likea a script. This design will be refined as we complete the implementation.
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 this
147 # A boolean flag which, if True, signals the kernel to execute this
148 # code as quietly as possible. This means that the kernel will compile
148 # code as quietly as possible. This means that the kernel will compile
149 # the code with 'exec' instead of 'single' (so sys.displayhook will not
149 # the code with 'exec' instead of 'single' (so sys.displayhook will not
150 # fire), and will *not*:
150 # 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 # The default is False.
154 # The default is False.
155 'silent' : bool,
155 'silent' : bool,
156 }
156 }
157
157
158 Upon execution, the kernel *always* sends a reply, with a status code
158 Upon execution, the kernel *always* sends a reply, with a status code
159 indicating what happened and additional data depending on the outcome.
159 indicating what happened and additional data depending on the outcome.
160
160
161 Message type: ``execute_reply``::
161 Message type: ``execute_reply``::
162
162
163 content = {
163 content = {
164 # One of: 'ok' OR 'error' OR 'abort'
164 # One of: 'ok' OR 'error' OR 'abort'
165 'status' : str,
165 'status' : str,
166
166
167 # Any additional data depends on status value
167 # Any additional data depends on status value
168 }
168 }
169
169
170 When status is 'ok', the following extra fields are present::
170 When status is 'ok', the following extra fields are present::
171
171
172 {
172 {
173 # This has the same structure as the output of a prompt request, but is
173 # This has the same structure as the output of a prompt request, but is
174 # for the client to set up the *next* prompt (with identical limitations
174 # for the client to set up the *next* prompt (with identical limitations
175 # to a prompt request)
175 # to a prompt request)
176 'next_prompt' : {
176 'next_prompt' : {
177 'prompt_string' : str,
177 'prompt_string' : str,
178 'prompt_number' : int,
178 'prompt_number' : int,
179 },
179 },
180
180
181 # The prompt number of the actual execution for this code, which may be
181 # The prompt number of the actual execution for this code, which may be
182 # different from the one used when the code was typed, which was the
182 # different from the one used when the code was typed, which was the
183 # 'next_prompt' field of the *previous* request. They will differ in the
183 # 'next_prompt' field of the *previous* request. They will differ in the
184 # case where there is more than one client talking simultaneously to a
184 # case where there is more than one client talking simultaneously to a
185 # kernel, since the numbers can go out of sync. GUI clients can use this
185 # kernel, since the numbers can go out of sync. GUI clients can use this
186 # to correct the previously written number in-place, terminal ones may
186 # to correct the previously written number in-place, terminal ones may
187 # re-print a corrected one if desired.
187 # re-print a corrected one if desired.
188 'prompt_number' : int,
188 'prompt_number' : int,
189
189
190 # The kernel will often transform the input provided to it. This
190 # The kernel will often transform the input provided to it. This
191 # contains the transformed code, which is what was actually executed.
191 # contains the transformed code, which is what was actually executed.
192 'transformed_code' : str,
192 'transformed_code' : str,
193
193
194 # The execution payload is a dict with string keys that may have been
194 # The execution payload is a dict with string keys that may have been
195 # produced by the code being executed. It is retrieved by the kernel at
195 # produced by the code being executed. It is retrieved by the kernel at
196 # the end of the execution and sent back to the front end, which can take
196 # the end of the execution and sent back to the front end, which can take
197 # action on it as needed. See main text for further details.
197 # action on it as needed. See main text for further details.
198 'payload' : dict,
198 'payload' : dict,
199 }
199 }
200
200
201 .. admonition:: Execution payloads
201 .. admonition:: Execution payloads
202
202
203 The notion of an 'execution payload' is different from a return value of a
203 The notion of an 'execution payload' is different from a return value of a
204 given set of code, which normally is just displayed on the pyout stream
204 given set of code, which normally is just displayed on the pyout stream
205 through the PUB socket. The idea of a payload is to allow special types of
205 through the PUB socket. The idea of a payload is to allow special types of
206 code, typically magics, to populate a data container in the IPython kernel
206 code, typically magics, to populate a data container in the IPython kernel
207 that will be shipped back to the caller via this channel. The kernel will
207 that will be shipped back to the caller via this channel. The kernel will
208 have an API for this, probably something along the lines of::
208 have an API for this, probably something along the lines of::
209
209
210 ip.exec_payload_add(key, value)
210 ip.exec_payload_add(key, value)
211
211
212 though this API is still in the design stages. The data returned in this
212 though this API is still in the design stages. The data returned in this
213 payload will allow frontends to present special views of what just happened.
213 payload will allow frontends to present special views of what just happened.
214
214
215
215
216 When status is 'error', the following extra fields are present::
216 When status is 'error', the following extra fields are present::
217
217
218 {
218 {
219 'exc_name' : str, # Exception name, as a string
219 'exc_name' : str, # Exception name, as a string
220 'exc_value' : str, # Exception value, as a string
220 'exc_value' : str, # Exception value, as a string
221
221
222 # The traceback will contain a list of frames, represented each as a
222 # The traceback will contain a list of frames, represented each as a
223 # string. For now we'll stick to the existing design of ultraTB, which
223 # string. For now we'll stick to the existing design of ultraTB, which
224 # controls exception level of detail statefully. But eventually we'll
224 # controls exception level of detail statefully. But eventually we'll
225 # want to grow into a model where more information is collected and
225 # want to grow into a model where more information is collected and
226 # packed into the traceback object, with clients deciding how little or
226 # packed into the traceback object, with clients deciding how little or
227 # how much of it to unpack. But for now, let's start with a simple list
227 # how much of it to unpack. But for now, let's start with a simple list
228 # of strings, since that requires only minimal changes to ultratb as
228 # of strings, since that requires only minimal changes to ultratb as
229 # written.
229 # written.
230 'traceback' : list,
230 'traceback' : list,
231 }
231 }
232
232
233
233
234 When status is 'abort', there are for now no additional data fields. This
234 When status is 'abort', there are for now no additional data fields. This
235 happens when the kernel was interrupted by a signal.
235 happens when the kernel was interrupted by a signal.
236
236
237
237
238 Prompt
238 Prompt
239 ------
239 ------
240
240
241 A simple request for a current prompt string.
241 A simple request for a current prompt string.
242
242
243 Message type: ``prompt_request``::
243 Message type: ``prompt_request``::
244
244
245 content = {}
245 content = {}
246
246
247 In the reply, the prompt string comes back with the prompt number placeholder
247 In the reply, the prompt string comes back with the prompt number placeholder
248 *unevaluated*. The message format is:
248 *unevaluated*. The message format is:
249
249
250 Message type: ``prompt_reply``::
250 Message type: ``prompt_reply``::
251
251
252 content = {
252 content = {
253 'prompt_string' : str,
253 'prompt_string' : str,
254 'prompt_number' : int,
254 'prompt_number' : int,
255 }
255 }
256
256
257 Clients can produce a prompt with ``prompt_string.format(prompt_number)``, but
257 Clients can produce a prompt with ``prompt_string.format(prompt_number)``, but
258 they should be aware that the actual prompt number for that input could change
258 they should be aware that the actual prompt number for that input could change
259 later, in the case where multiple clients are interacting with a single
259 later, in the case where multiple clients are interacting with a single
260 kernel.
260 kernel.
261
261
262
262
263 Object information
263 Object information
264 ------------------
264 ------------------
265
265
266 One of IPython's most used capabilities is the introspection of Python objects
266 One of IPython's most used capabilities is the introspection of Python objects
267 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
267 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
268 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
268 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
269 enough that it warrants an explicit message type, especially because frontends
269 enough that it warrants an explicit message type, especially because frontends
270 may want to get object information in response to user keystrokes (like Tab or
270 may want to get object information in response to user keystrokes (like Tab or
271 F1) besides from the user explicitly typing code like ``x??``.
271 F1) besides from the user explicitly typing code like ``x??``.
272
272
273 Message type: ``object_info_request``::
273 Message type: ``object_info_request``::
274
274
275 content = {
275 content = {
276 # The (possibly dotted) name of the object to be searched in all
276 # The (possibly dotted) name of the object to be searched in all
277 # relevant namespaces
277 # relevant namespaces
278 'name' : str,
278 'name' : str,
279
279
280 # The level of detail desired. The default (0) is equivalent to typing
280 # The level of detail desired. The default (0) is equivalent to typing
281 # 'x?' at the prompt, 1 is equivalent to 'x??'.
281 # 'x?' at the prompt, 1 is equivalent to 'x??'.
282 'detail_level' : int,
282 'detail_level' : int,
283 }
283 }
284
284
285 The returned information will be a dictionary with keys very similar to the
285 The returned information will be a dictionary with keys very similar to the
286 field names that IPython prints at the terminal.
286 field names that IPython prints at the terminal.
287
287
288 Message type: ``object_info_reply``::
288 Message type: ``object_info_reply``::
289
289
290 content = {
290 content = {
291 # Flags for magics and system aliases
291 # Flags for magics and system aliases
292 'ismagic' : bool,
292 'ismagic' : bool,
293 'isalias' : bool,
293 'isalias' : bool,
294
294
295 # The name of the namespace where the object was found ('builtin',
295 # The name of the namespace where the object was found ('builtin',
296 # 'magics', 'alias', 'interactive', etc.)
296 # 'magics', 'alias', 'interactive', etc.)
297 'namespace' : str,
297 'namespace' : str,
298
298
299 # The type name will be type.__name__ for normal Python objects, but it
299 # The type name will be type.__name__ for normal Python objects, but it
300 # can also be a string like 'Magic function' or 'System alias'
300 # can also be a string like 'Magic function' or 'System alias'
301 'type_name' : str,
301 'type_name' : str,
302
302
303 'string_form' : str,
303 'string_form' : str,
304
304
305 # For objects with a __class__ attribute this will be set
305 # For objects with a __class__ attribute this will be set
306 'base_class' : str,
306 'base_class' : str,
307
307
308 # For objects with a __len__ attribute this will be set
308 # For objects with a __len__ attribute this will be set
309 'length' : int,
309 'length' : int,
310
310
311 # If the object is a function, class or method whose file we can find,
311 # If the object is a function, class or method whose file we can find,
312 # we give its full path
312 # we give its full path
313 'file' : str,
313 'file' : str,
314
314
315 # For pure Python callable objects, we can reconstruct the object
315 # For pure Python callable objects, we can reconstruct the object
316 # definition line which provides its call signature
316 # definition line which provides its call signature
317 'definition' : str,
317 'definition' : str,
318
318
319 # For instances, provide the constructor signature (the definition of
319 # For instances, provide the constructor signature (the definition of
320 # the __init__ method):
320 # the __init__ method):
321 'init_definition' : str,
321 'init_definition' : str,
322
322
323 # Docstrings: for any object (function, method, module, package) with a
323 # Docstrings: for any object (function, method, module, package) with a
324 # docstring, we show it. But in addition, we may provide additional
324 # docstring, we show it. But in addition, we may provide additional
325 # docstrings. For example, for instances we will show the constructor
325 # docstrings. For example, for instances we will show the constructor
326 # and class docstrings as well, if available.
326 # and class docstrings as well, if available.
327 'docstring' : str,
327 'docstring' : str,
328
328
329 # For instances, provide the constructor and class docstrings
329 # For instances, provide the constructor and class docstrings
330 'init_docstring' : str,
330 'init_docstring' : str,
331 'class_docstring' : str,
331 'class_docstring' : str,
332
332
333 # If detail_level was 1, we also try to find the source code that
333 # If detail_level was 1, we also try to find the source code that
334 # defines the object, if possible. The string 'None' will indicate
334 # defines the object, if possible. The string 'None' will indicate
335 # that no source was found.
335 # that no source was found.
336 'source' : str,
336 'source' : str,
337 }
337 }
338
338
339
339
340 Complete
340 Complete
341 --------
341 --------
342
342
343 Message type: ``complete_request``::
343 Message type: ``complete_request``::
344
344
345 content = {
345 content = {
346 # The text to be completed, such as 'a.is'
346 # The text to be completed, such as 'a.is'
347 'text' : str,
347 'text' : str,
348
348
349 # The full line, such as 'print a.is'. This allows completers to
349 # The full line, such as 'print a.is'. This allows completers to
350 # make decisions that may require information about more than just the
350 # make decisions that may require information about more than just the
351 # current word.
351 # current word.
352 'line' : str,
352 'line' : str,
353 }
353 }
354
354
355 Message type: ``complete_reply``::
355 Message type: ``complete_reply``::
356
356
357 content = {
357 content = {
358 # The list of all matches to the completion request, such as
358 # The list of all matches to the completion request, such as
359 # ['a.isalnum', 'a.isalpha'] for the above example.
359 # ['a.isalnum', 'a.isalpha'] for the above example.
360 'matches' : list
360 'matches' : list
361 }
361 }
362
362
363
363
364 History
364 History
365 -------
365 -------
366
366
367 For clients to explicitly request history from a kernel. The kernel has all
367 For clients to explicitly request history from a kernel. The kernel has all
368 the actual execution history stored in a single location, so clients can
368 the actual execution history stored in a single location, so clients can
369 request it from the kernel when needed.
369 request it from the kernel when needed.
370
370
371 Message type: ``history_request``::
371 Message type: ``history_request``::
372
372
373 content = {
373 content = {
374
374
375 # If true, also return output history in the resulting dict.
375 # If true, also return output history in the resulting dict.
376 'output' : bool,
376 'output' : bool,
377
377
378 # This parameter can be one of: A number, a pair of numbers, 'all'
378 # This parameter can be one of: A number, a pair of numbers, 'all'
379 # If not given, last 40 are returned.
379 # If not given, last 40 are returned.
380 # - number n: return the last n entries.
380 # - number n: return the last n entries.
381 # - pair n1, n2: return entries in the range(n1, n2).
381 # - pair n1, n2: return entries in the range(n1, n2).
382 # - 'all': return all history
382 # - 'all': return all history
383 'range' : n or (n1, n2) or 'all',
383 'range' : n or (n1, n2) or 'all',
384
384
385 # If a filter is given, it is treated as a regular expression and only
385 # If a filter is given, it is treated as a regular expression and only
386 # matching entries are returned. re.search() is used to find matches.
386 # matching entries are returned. re.search() is used to find matches.
387 'filter' : str,
387 'filter' : str,
388 }
388 }
389
389
390 Message type: ``history_reply``::
390 Message type: ``history_reply``::
391
391
392 content = {
392 content = {
393 # A list of (number, input) pairs
393 # A list of (number, input) pairs
394 'input' : list,
394 'input' : list,
395
395
396 # A list of (number, output) pairs
396 # A list of (number, output) pairs
397 'output' : list,
397 'output' : list,
398 }
398 }
399
399
400
401 Control
402 -------
403
404 Message type: ``heartbeat``::
405
406 content = {
407 # FIXME - unfinished
408 }
409
410
400
411 Messages on the PUB/SUB socket
401 Messages on the PUB/SUB socket
412 ==============================
402 ==============================
413
403
414 Streams (stdout, stderr, etc)
404 Streams (stdout, stderr, etc)
415 ------------------------------
405 ------------------------------
416
406
417 Message type: ``stream``::
407 Message type: ``stream``::
418
408
419 content = {
409 content = {
420 # The name of the stream is one of 'stdin', 'stdout', 'stderr'
410 # The name of the stream is one of 'stdin', 'stdout', 'stderr'
421 'name' : str,
411 'name' : str,
422
412
423 # The data is an arbitrary string to be written to that stream
413 # The data is an arbitrary string to be written to that stream
424 'data' : str,
414 'data' : str,
425 }
415 }
426
416
427 When a kernel receives a raw_input call, it should also broadcast it on the pub
417 When a kernel receives a raw_input call, it should also broadcast it on the pub
428 socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
418 socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
429 to monitor/display kernel interactions and possibly replay them to their user
419 to monitor/display kernel interactions and possibly replay them to their user
430 or otherwise expose them.
420 or otherwise expose them.
431
421
432 Python inputs
422 Python inputs
433 -------------
423 -------------
434
424
435 These messages are the re-broadcast of the ``execute_request``.
425 These messages are the re-broadcast of the ``execute_request``.
436
426
437 Message type: ``pyin``::
427 Message type: ``pyin``::
438
428
439 content = {
429 content = {
440 # Source code to be executed, one or more lines
430 # Source code to be executed, one or more lines
441 'code' : str
431 'code' : str
442 }
432 }
443
433
444 Python outputs
434 Python outputs
445 --------------
435 --------------
446
436
447 When Python produces output from code that has been compiled in with the
437 When Python produces output from code that has been compiled in with the
448 'single' flag to :func:`compile`, any expression that produces a value (such as
438 'single' flag to :func:`compile`, any expression that produces a value (such as
449 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
439 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
450 this value whatever it wants. The default behavior of ``sys.displayhook`` in
440 this value whatever it wants. The default behavior of ``sys.displayhook`` in
451 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
441 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
452 the value as long as it is not ``None`` (which isn't printed at all). In our
442 the value as long as it is not ``None`` (which isn't printed at all). In our
453 case, the kernel instantiates as ``sys.displayhook`` an object which has
443 case, the kernel instantiates as ``sys.displayhook`` an object which has
454 similar behavior, but which instead of printing to stdout, broadcasts these
444 similar behavior, but which instead of printing to stdout, broadcasts these
455 values as ``pyout`` messages for clients to display appropriately.
445 values as ``pyout`` messages for clients to display appropriately.
456
446
457 Message type: ``pyout``::
447 Message type: ``pyout``::
458
448
459 content = {
449 content = {
460 # The data is typically the repr() of the object.
450 # The data is typically the repr() of the object.
461 'data' : str,
451 'data' : str,
462
452
463 # The prompt number for this execution is also provided so that clients
453 # The prompt number for this execution is also provided so that clients
464 # can display it, since IPython automatically creates variables called
454 # can display it, since IPython automatically creates variables called
465 # _N (for prompt N).
455 # _N (for prompt N).
466 'prompt_number' : int,
456 'prompt_number' : int,
467 }
457 }
468
458
469 Python errors
459 Python errors
470 -------------
460 -------------
471
461
472 When an error occurs during code execution
462 When an error occurs during code execution
473
463
474 Message type: ``pyerr``::
464 Message type: ``pyerr``::
475
465
476 content = {
466 content = {
477 # Similar content to the execute_reply messages for the 'error' case,
467 # Similar content to the execute_reply messages for the 'error' case,
478 # except the 'status' field is omitted.
468 # except the 'status' field is omitted.
479 }
469 }
480
470
481 Kernel crashes
471 Kernel crashes
482 --------------
472 --------------
483
473
484 When the kernel has an unexpected exception, caught by the last-resort
474 When the kernel has an unexpected exception, caught by the last-resort
485 sys.excepthook, we should broadcast the crash handler's output before exiting.
475 sys.excepthook, we should broadcast the crash handler's output before exiting.
486 This will allow clients to notice that a kernel died, inform the user and
476 This will allow clients to notice that a kernel died, inform the user and
487 propose further actions.
477 propose further actions.
488
478
489 Message type: ``crash``::
479 Message type: ``crash``::
490
480
491 content = {
481 content = {
492 # Similarly to the 'error' case for execute_reply messages, this will
482 # Similarly to the 'error' case for execute_reply messages, this will
493 # contain exc_name, exc_type and traceback fields.
483 # contain exc_name, exc_type and traceback fields.
494
484
495 # An additional field with supplementary information such as where to
485 # An additional field with supplementary information such as where to
496 # send the crash message
486 # send the crash message
497 'info' : str,
487 'info' : str,
498 }
488 }
499
489
500
490
501 Future ideas
491 Future ideas
502 ------------
492 ------------
503
493
504 Other potential message types, currently unimplemented, listed below as ideas.
494 Other potential message types, currently unimplemented, listed below as ideas.
505
495
506 Message type: ``file``::
496 Message type: ``file``::
507
497
508 content = {
498 content = {
509 'path' : 'cool.jpg',
499 'path' : 'cool.jpg',
510 'mimetype' : str,
500 'mimetype' : str,
511 'data' : str,
501 'data' : str,
512 }
502 }
513
503
514
504
515 Messages on the REQ/REP socket
505 Messages on the REQ/REP socket
516 ==============================
506 ==============================
517
507
518 This is a socket that goes in the opposite direction: from the kernel to a
508 This is a socket that goes in the opposite direction: from the kernel to a
519 *single* frontend, and its purpose is to allow ``raw_input`` and similar
509 *single* frontend, and its purpose is to allow ``raw_input`` and similar
520 operations that read from ``sys.stdin`` on the kernel to be fulfilled by the
510 operations that read from ``sys.stdin`` on the kernel to be fulfilled by the
521 client. For now we will keep these messages as simple as possible, since they
511 client. For now we will keep these messages as simple as possible, since they
522 basically only mean to convey the ``raw_input(prompt)`` call.
512 basically only mean to convey the ``raw_input(prompt)`` call.
523
513
524 Message type: ``input_request``::
514 Message type: ``input_request``::
525
515
526 content = { 'prompt' : str }
516 content = { 'prompt' : str }
527
517
528 Message type: ``input_reply``::
518 Message type: ``input_reply``::
529
519
530 content = { 'value' : str }
520 content = { 'value' : str }
531
521
532 .. Note::
522 .. Note::
533
523
534 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
524 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
535 practice the kernel should behave like an interactive program. When a
525 practice the kernel should behave like an interactive program. When a
536 program is opened on the console, the keyboard effectively takes over the
526 program is opened on the console, the keyboard effectively takes over the
537 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
527 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
538 Since the IPython kernel effectively behaves like a console program (albeit
528 Since the IPython kernel effectively behaves like a console program (albeit
539 one whose "keyboard" is actually living in a separate process and
529 one whose "keyboard" is actually living in a separate process and
540 transported over the zmq connection), raw ``stdin`` isn't expected to be
530 transported over the zmq connection), raw ``stdin`` isn't expected to be
541 available.
531 available.
542
532
533
534 Heartbeat for kernels
535 =====================
536
537 Initially we had considered using messages like those above over ZMQ for a
538 kernel 'heartbeat' (a way to detect quickly and reliably whether a kernel is
539 alive at all, even if it may be busy executing user code). But this has the
540 problem that if the kernel is locked inside extension code, it wouldn't execute
541 the python heartbeat code. But it turns out that we can implement a basic
542 heartbeat with pure ZMQ, without using any Python messaging at all.
543
544 The monitor sends out a single zmq message (right now, it is a str of the
545 monitor's lifetime in seconds), and gets the same message right back, prefixed
546 with the zmq identity of the XREQ socket in the heartbeat process. This can be
547 a uuid, or even a full message, but there doesn't seem to be a need for packing
548 up a message when the sender and receiver are the exact same Python object.
549
550 The model is this::
551
552 monitor.send(str(self.lifetime)) # '1.2345678910'
553
554 and the monitor receives some number of messages of the form::
555
556 ['uuid-abcd-dead-beef', '1.2345678910']
557
558 where the first part is the zmq.IDENTITY of the heart's XREQ on the engine, and
559 the rest is the message sent by the monitor. No Python code ever has any
560 access to the message between the monitor's send, and the monitor's recv.
561
543
562
544 ToDo
563 ToDo
545 ====
564 ====
546
565
547 Missing things include:
566 Missing things include:
548
567
549 * Important: finish thinking through the payload concept and API.
568 * Important: finish thinking through the payload concept and API.
550
569
551 * Important: ensure that we have a good solution for magics like %edit. It's
570 * Important: ensure that we have a good solution for magics like %edit. It's
552 likely that with the payload concept we can build a full solution, but not
571 likely that with the payload concept we can build a full solution, but not
553 100% clear yet.
572 100% clear yet.
554
573
555 * Finishing the details of the heartbeat protocol.
574 * Finishing the details of the heartbeat protocol.
556
575
557 * Signal handling: specify what kind of information kernel should broadcast (or
576 * Signal handling: specify what kind of information kernel should broadcast (or
558 not) when it receives signals.
577 not) when it receives signals.
559
578
560 .. include:: ../links.rst
579 .. include:: ../links.rst
General Comments 0
You need to be logged in to leave comments. Login now