{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this notebook, we will demonstrate persistent displays for function calls; each time the same function runs the same display will continue to update.\n",
"\n",
"This is my first foray into doing weird stuff in `IPython` with notebooks. [IPython 7.0](https://blog.jupyter.org/ipython-7-0-async-repl-a35ce050f7f7)\n",
"introduces async
conventions into the IPython shell. Now it is time to start using them in the notebook. "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
" import IPython, asyncio, inspect, time"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`f` is a function that returns a __plain/text__ value. In the signature, we assign a default display object that will\n",
"persist through out the same session. After the body of the function evaluates we must update the display by hand."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"100"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
" async def f(x, display=IPython.display.display(None, display_id=True)):\n",
" time.sleep(4)\n",
" return display.update(x) or x"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Calling display in the function signature will attach the output to the function definition cell. And that output is updated\n",
"each time the function is executed."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
" assert inspect.iscoroutinefunction(f)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`asyncio.ensure_future` will run `f` concurrently, but it will not block our notebook session."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time: 0 ns\n"
]
}
],
"source": [
" %time task = asyncio.ensure_future(f(10))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We time the cell executed above and notice that it occurs instantaneously.\n",
"\n",
"> This demo uses Python 3.6 so we cannot use [`asyncio.create_task`](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task) which is new in Python 3.7."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
" assert inspect.isawaitable(task), \"\"\"A special feature of asyncrohonous function calls that they are awaitable.\"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When task finishes the display assigned in `f`'s signature is updated with the new value eventually. The same output is updated when the function is run again."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time: 0 ns\n"
]
}
],
"source": [
" %time task = asyncio.ensure_future(f(100))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Similarly, the cell execution instant while the evaluation is occuring the background."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Other display types\n",
"\n",
"It is important to know the display type before creating an output. For example, if we wanted to the perform the same operation \n",
"on `pandas` we would have to create an HTML display ahead of time."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n", " | A | \n", "B | \n", "C | \n", "D | \n", "
---|---|---|---|---|
dQk4N8kDJr | \n", "0.053310 | \n", "-0.025388 | \n", "0.115704 | \n", "-1.712441 | \n", "
PDAW37TO9p | \n", "1.016993 | \n", "-0.686832 | \n", "2.188959 | \n", "-0.233486 | \n", "
lfSmzMsnAL | \n", "-0.504652 | \n", "1.566282 | \n", "-0.029445 | \n", "-0.767817 | \n", "