3

I would like to wait to asynchronous jupyter widget events while the cell is blocked executing async code (thus, usually idle, waiting for I/O, utilising the %autowait magic). Unfortunately, the jupyter notebook does not seem to send any traitlet events while the cell is blocking. The documentation above circumvents this, by sending the callback into the "background", so it can react after the cell has finished executing. I would like to avoid that, because it make reasoning about background tasks harder than it needs to be; it's precisely against the principles of my favourite async event loop in python: trio. Is there a way to make that work?

Here is the example from the jupyter docs adapted to trio (though it fails the same way with asyncio):

import trio

from IPython.display import display
from ipywidgets import IntSlider, Output

%autoawait trio

async def wait_for_change(widget, attribute):
    result = None
    evt = trio.Event()
    def value_changed(change):
        nonlocal result
        result = change
        evt.set()
    widget.observe(value_changed, attribute)
    try:
        await evt.wait()
    finally:
        widget.unobserve(value_changed, attribute)
    return result

slider = IntSlider()
out = Output()

display(slider)
display(out)

# at this point, the widgets are visible

for i in range(10):
    out.append_stdout('did work ' + str(i) + '\n')
    # here, the cell blocks thanks to the `%autoawait` above -
    # but jupyter fails to forward any events
    x = await wait_for_change(slider, 'value')
    out.append_stdout('async function continued with value ' + str(x) + '\n')
burnpanck
  • 1,955
  • 1
  • 12
  • 36
  • I don't have a full answer for you, but as a hint you might be able to get something to work with Trio's [guest mode](https://trio.readthedocs.io/en/stable/reference-lowlevel.html#using-guest-mode-to-run-trio-on-top-of-other-event-loops). The fact that Jupyter supports callbacks must mean that it has its own underlying event loop of some sort, so Trio could be a guest on that. But, unless someone's done the work of integrating them already, it might be a bit fiddly. (But less then you might imagine, thanks to Trio's impressive guest mode.) – Arthur Tacca Dec 28 '21 at 12:07
  • @ArthurTacca: Actually, I believe that is what `%autoawait trio` does - it integrates a trio-compatible event loop with Jupyter's own event loop such that trio stuff just works. The problem above however is not with trio at all (it fails in the same way with asyncio) - the problem is that jupyter's own event loop seems to be blocked/locked while the cell is executing. The "official solution" works only when the cell is not executing, requiring the callback to be "sent into space" which is against the philosophy of trio (or structured concurrency in general). – burnpanck Mar 10 '22 at 23:02

0 Answers0