Pause python to wait for user interaction

What I need to do is a function that would pause the script execution and display a “continue” button widget which would resume the execution after being pushed. The function would be used like so:

print("Hello, please push the continue button")
displayContinueAndWaitForPress()
print("You have pushed the button, congratulations I guess.")

As trivial as this looks like, I am having a very hard time to make it to work.
The Jupyter doc provides two ways to do it: Asynchronous and Generator based.

I can’t used the asynchronous method as my function will be implemented in a bigger script that is not running in an async loop.

The generator based function does print some stuff after pressing the button, but it doesn’t seem to stop the execution the way I would need it to, and shows “You have pushed the button, congratulations I guess.” before I press the button.

Here’s the code I’m using:

from functools import wraps
def yield_for_change(widget):
    def f(iterator):
        @wraps(iterator)
        def inner():
            i = iterator()
            def next_i(change):
                try:
                    i.send(change)
                except StopIteration as e:
                    widget.unobserve(next_i, attribute)
            widget.on_click(next_i)
            # start the generator
            next(i)
        return inner
    return f

from ipywidgets import Button
button=Button()


@yield_for_change(button)
def f():
    for i in range(10):
        print('did work %s'%i)
        x = yield


def displayContinueAndWaitForPress():
    f()
    display(button)

/

print("Hello, please push the continue button")
displayContinueAndWaitForPress()
print("You have pushed the button, congratulations I guess.")

I am not very well experienced with Python and Jupiter but do you see what’s my problem? I’m surpised a library such a ipwidgets makes it so easy to make layouts but doesn’t provide much help with a use like mine.

Thank you for your help,
Kromahtique

I think what you are describing is very similar to what dpgoldenberg was asking here.
My answer slightly modified from there to do what you want is:

# sort of based on https://github.com/voila-dashboards/voila-material/issues/18
import ipywidgets as widgets
from IPython.display import display
output = widgets.Output()

@output.capture(clear_output=False,wait=True) # based on https://github.com/jupyter-widgets/ipywidgets/issues/1846 and https://ipywidgets.readthedocs.io/en/latest/examples/Output%20Widget.html
def sayHello(b):
    print("You have pushed the button, congratulations I guess.")

run_button = widgets.Button(
      description = 'continue'
)
print("Hello, please push the continue button")
run_button.on_click(sayHello)
display(run_button)
output

And if you don’t need a widget to do this, there other more traditional ways in Jupyter to do something along the lines of what you describe.
For example, see trick #3: ‘Run Demos’ from here.
Or see the image in the GtiHub repository here and note the text, Press Enter to continue... at the bottom of the image under ‘How to play’. The code for that prompt can be found here. Note the use of input(). Sadly, the Binder version of that no longer runs (launch link should be this but the image won’t build ), and so I you cannot easily run the simulation to see how the prompts keep allowing you to step forward through things. However, I placed the pertinent code to demonstrate the use of input() in this gist. You can take the python code from there and place it in a Jupyter cell and start stepping through some of the first steps. It is enough to get a sense of how input() works before the code errors out.

1 Like