When is a widget property available to an iPython / Jupyter cell?

I’m getting ready to create a communications widget for use in a Jupyter application. I’m trying to understand when the widget’s “value” property can be accessed … it looks like the “value” can be read anytime, but won’t match the widget model “value” until cell execution stops (i.e., the widget’s browser state isn’t updated back to the widget’s kernel state).

To test this, I tried creating a small slider widget, waiting for 10 seconds, and then reading the widget “value” property … all in the same cell. In the 10 seconds, the user (i.e., me) has time to change the slider to something like “5”.

Here’s a small test that can be run in a cell. When the sleep() happens, I move the slider to value “5”.

    from ipywidgets import *
    import time

    slider = IntSlider(
        value=7,
        min=1,
        max=10.0,
        step=1,
        description="Input:",
    )

    display(slider)
    time.sleep(10) # move slider to 5
    print("done " + str(slider.value))

I expected “done 5” but got “done 7”, implying to me that “value” is updated only after the cell completes.

Is this always true? And is there a way to force synchronization between the widget’s browser state and its state in the kernel?

(I do get the expected “done 5” if I move the print() to the following cell.)

Thanks!

Python model of the underlying widget will not update while cell is still executing. The GUI will update, and will appear responsive, because underlying JavaScript runs, but updated value won’t make it to Python side while notebook cell is still executing. Events generated by JavaScript won’t execute concurrently with cell execution, but only in between cells.

It is often surprising to new users of ipywidgets, but that’s how IPython works. It is actually quite difficult, but not impossible, to execute UI events while executing a long running cell. I have written a library to achieve this, see this thread: Interactive widgets while executing long-running cell

Thank you! This is very helpful.

I have been reading about asyncio (https://realpython.com/async-io-python/) and its application to widgets (https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Asynchronous.html). I can see how waiting on a widget could be possible with just asyncio.

Your jupyter-ui-poll seems more straightforward.

My ultimate application is to enable biological workflows to be written in Jupyter. Not a big problem. The issue arises when the workflow needs to call a service that’s running on the user’s PC while the notebook may be running in the cloud.

I’m going to use the browser to communicate with the PC-based service, but the result has to be available to the python application running in the cloud. Widgets seem natural for this.

But I also want the service result to be available inline to the Python application … therefore the need for your library (or something like it). Otherwise, I’d be inflicting a nightmare on the workflow writer by forcing judicious and unnatural packaging of workflow steps into cells … and nevermind the difficulty of writing a loop calling the service.

So, the service results really do need to be available inline, and then the workflow writer can package workflow steps into cells more naturally for the workflow itself.

(I’ll likely bury the polling in a helper routine that calls the service and returns the result. I don’t think the workflow writer will notice much, if anything of your library … which is perfect.)

Sound right?? Or am I missing something big?? (I’m a newbie Python programmer … still learning.)

Thanks!

Glad that helped.

You can absolutely implement your workflow with either just callbacks or in async style. Those approaches have advantages (no polling needed). But they also require a very different paradigm than a more straightforward, linear programming style. Well, async is kinda linear, unlike callback events, but does require extra syntax and a relatively steep learning curve if you haven’t done it before.

I should mention that there is this library: ipython_blocking, and in fact all the hard work of figuring out how to make this work was done by the author of ipython_blocking with the help of IPython developers. I have re-used all those ideas but with a different API that suits my needs better, ipython_blocking is more focused on notebook magics.