When a user connects to a Jupyter kernel and executes code, the kernel responds back with a JSON payload that represents the output of the execution. There are four different types of outputs that a kernel can return.
stream
error
display_data
execute_result
Let's dive into each of these output types one-by-one.
stream
outputs are returned when a programs executions outputs something to standard out or standard error. For example, printing out a string using Python's print function...
print("This is a stream output")
...will return a stream
output.
{
"header": {
"msg_id": "70d5a868-32ab31c51f0a6f59ef7ae31b",
"msg_type": "stream",
"username": "jovyan",
"session": "2c9cc318-a9de7a828cb72082a25e021e",
"date": "2020-01-20T17:48:14.040265Z",
"version": "5.3"
},
"msg_id": "70d5a868-32ab31c51f0a6f59ef7ae31b",
"msg_type": "stream",
"parent_header": {
"msg_id": "e554b829ced3492cb5af2c3cca12359e",
"username": "username",
"session": "f99df3a00a7647b48a31e095bb186dfb",
"msg_type": "execute_request",
"version": "5.2",
"date": "2020-01-20T17:48:14.035150Z"
},
"metadata": {},
"content": { "name": "stdout", "text": "This is a stream output\n" },
"buffers": [],
"channel": "iopub"
}
Executing a command line method using the !
operator...
!pwd
...will also return a stream output.
{
"header": {
"msg_id": "8e818c63-851893589050b90014b5f89a",
"msg_type": "stream",
"username": "jovyan",
"session": "2c9cc318-a9de7a828cb72082a25e021e",
"date": "2020-01-20T17:49:35.315712Z",
"version": "5.3"
},
"msg_id": "8e818c63-851893589050b90014b5f89a",
"msg_type": "stream",
"parent_header": {
"msg_id": "62d2674f18ed411d8e280f64171a7000",
"username": "username",
"session": "f99df3a00a7647b48a31e095bb186dfb",
"msg_type": "execute_request",
"version": "5.2",
"date": "2020-01-20T17:49:34.721649Z"
},
"metadata": {},
"content": { "name": "stdout", "text": "/home/jovyan\r\n" },
"buffers": [],
"channel": "iopub"
}
error
outputs are returned whenever the executed code raised a runtime exception. This will often happen if there is a syntax error or a referenced to an undefined variable in the code. For example, executing the following code...
print("I want to print an undefined variable: ", never_defined)
...will return the following JSON response from the kernel.
{
"header": {
"msg_id": "f6b6909d-9695100a8b8bec8920a314a1",
"msg_type": "error",
"username": "jovyan",
"session": "2c9cc318-a9de7a828cb72082a25e021e",
"date": "2020-01-20T17:54:18.907444Z",
"version": "5.3"
},
"msg_id": "f6b6909d-9695100a8b8bec8920a314a1",
"msg_type": "error",
"parent_header": {
"msg_id": "9dfcbd997057474ca7ba743847783b22",
"username": "username",
"session": "f99df3a00a7647b48a31e095bb186dfb",
"msg_type": "execute_request",
"version": "5.2",
"date": "2020-01-20T17:54:18.830166Z"
},
"metadata": {},
"content": {
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-3-84e3ac9791e4>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"I want to print an undefined variable: \"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnever_defined\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mNameError\u001b[0m: name 'never_defined' is not defined"
],
"ename": "NameError",
"evalue": "name 'never_defined' is not defined"
},
"buffers": [],
"channel": "iopub"
}
Note that the content of the error response is an ANSI-encoded string. nteract uses the ansi-to-react package to render this string in the user interface.
display_data
outputs are returned when the code executed returns a Jupyter display object. Often, these outputs are images, data visualizations, HTML objects, and other rich media types that users can return from their outputs. For example, the following code snippet...
from IPython import display
from IPython.display import Image
display(Image(url='https://avatars2.githubusercontent.com/u/12401040?v=3&s=200'))
...will return the following JSON response.
{
"header": {
"msg_id": "b61e1899-8a11af128f44b592010e7aee",
"msg_type": "display_data",
"username": "jovyan",
"session": "160b4da4-52b4a799778387233561e04b",
"date": "2020-01-20T18:02:34.060820Z",
"version": "5.3"
},
"msg_id": "b61e1899-8a11af128f44b592010e7aee",
"msg_type": "display_data",
"parent_header": {
"msg_id": "13ed849a58f34c27992560425fec8ab4",
"username": "username",
"session": "56c4c34a426b4db5845995ade394d6c8",
"msg_type": "execute_request",
"version": "5.2",
"date": "2020-01-20T18:02:34.054765Z"
},
"metadata": {},
"content": {
"data": {
"text/html": "<img src=\"https://avatars2.githubusercontent.com/u/12401040?v=3&s=200\"/>",
"text/plain": "<IPython.core.display.Image object>"
},
"metadata": {},
"transient": {}
},
"buffers": [],
"channel": "iopub"
}
Let's take a closer look at the content of this response.
{
"content": {
"data": {
"text/html": "<img src=\"https://avatars2.githubusercontent.com/u/12401040?v=3&s=200\"/>",
"text/plain": "<IPython.core.display.Image object>"
},
"metadata": {},
"transient": {}
}
}
The data
property consists of a JSON payload that contains two values. Both values are keyed by their media type: text/html
and text/plain
. Generally, display_data
response will have multiple representations for the same output. Here, we have a representation that renders HTML and a representation that renders a plain-text string. In nteract, the outputs package will attempt to render the richest of the two media types in the UI. In this case, that would be the HTML representation. For more information on this, check out the transforms section of the documentation.
execute_result
responses are identical to display_data
response with the notable exception that they contain the execution count of the response. The execution count is a monotonically increasing count of the number of executions run against the kernel. execute_result
and display_data
responses are rendered in an identical way in the user interface.