Jupyter And Timer Functions?
Solution 1:
Ok, got somewhere, thanks to these:
- Coroutine as background job in Jupyter notebook
- Launching a python script as a background job on Jupyter
- a new thread for running a cell in ipython/jupyter notebook
First of all, here is a reworked simple example from the link above, which shows the use of IPython.lib.backgroundjobs.BackgroundJobManager
:
#https://stackoverflow.com/questions/32081926/a-new-thread-for-running-a-cell-in-ipython-jupyter-notebook##github.com/jupyter/ngcm-tutorial/blob/master/Day-1/IPython%20Kernel/Background%20Jobs.ipynbimport sched, time # NOTE: without this import, we'll get "Dead jobs:" instead of "Running jobs:" - exception at time.sleep will not be reported as such!from IPython.lib import backgroundjobs as bg
jobs = bg.BackgroundJobManager()
defprintfunc(interval=1, reps=5):
for n inrange(reps):
time.sleep(interval)
print('In the background... %i' % n)
#sys.stdout.flush() # flush breaks the thread in Jupyter, after first printout!print('All done!')
#sys.stdout.flush()#jobs.new('printfunc(1,3)') # works; prints: <BackgroundJob #0: printfunc(1,3)>
jobs.new(printfunc, 1, 3) # works; prints: <BackgroundJob #0: <function printfunc at 0x0000017120038730>>
jobs.status() # prints: "Running jobs:" "0 : <function printfunc at 0x00000171200389D8>" or "0 : printfunc(1,3)"
Here is how it looks like in Jupyter notebook:
That lead finally to getting the OP example to work - simply, by having the scheduler.run
be called through jobs.new
:
import plotly.graph_objs as go
import numpy as np
import sched, time
import random
from ipywidgets import widgets
from IPython.lib import backgroundjobs as bg
jobs = bg.BackgroundJobManager()
xs = np.linspace(0, 10, 100)
ys = np.zeros(100)
fig = go.FigureWidget()
fig.add_trace(go.Scatter(x=xs, y=ys,
mode='lines',
name='Random'))
fig.update_xaxes(range=[0, 10])
fig.update_yaxes(range=[0, 10])
s = sched.scheduler(time.time, time.sleep)
yi = 0
do_run_tick_func = Truedeftick_func(sc):
global ys, yi
if do_run_tick_func:
ys[yi] = random.random() * 10
yi = (yi+1)%100
fig.data[0].y = ys
s.enterabs(time.time()+1, 1, tick_func, (sc,))
else:
print("Exiting tick_func (not recheduling)") # this does not print on page#s.enterabs(time.time()+15, 1, tick_func, (s,))#s.run() # kills widget#s.run()#jobs.new(s.enterabs, time.time()+2, 1, tick_func, (s,)) # Does not run in loop, but says: Completed jobs: 0 : <bound method scheduler.enterabs of <sched.scheduler object at 0x000001E01CF12978>>#jobs.new(tick_func, s) # runs once, does not loop: Allo 0; Completed jobs: 0 : <function tick_func at 0x0000017120038400>
s.enterabs(time.time()+1, 1, tick_func, (s,))
jobs.new(s.run) # runs in loop! Running jobs: 0 : <bound method scheduler.run of <sched.scheduler object at 0x0000017120058390>>#jobs.status() # prints: "Running jobs:" ...# https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Events.html
output = widgets.Output()
mybuttonstop = widgets.Button(description="Stop Background Thread")
mybuttonstart = widgets.Button(description="Start Background Thread")
defon_button_stop_clicked(b):
global do_run_tick_func
print("Button clicked - stopping background thread...") # this does print on page
do_run_tick_func = Falsewith output:
print("print, with output?") # this does not print on pagedefon_button_start_clicked(b):
global do_run_tick_func
print("Button clicked - starting background thread...") # this does print on page
do_run_tick_func = True
s.enterabs(time.time()+1, 1, tick_func, (s,))
jobs.new(s.run)
mybuttonstop.on_click(on_button_stop_clicked)
mybuttonstart.on_click(on_button_start_clicked)
myhbox = widgets.HBox([mybuttonstart, mybuttonstop])
widgets.VBox([myhbox, fig])
Here is how this looks like in Jupyter notebook:
Solution 2:
The basic problem is that the code cell which displays a widget must finish executing before the widget will display.
What you need is a way for the widget to call back to the Python kernel after it has initialized in order to request an update. You could implement this using proxy widgets like this.
You can also combine proxy widgets with other widget types using HBox, etcetera and use the proxy widget for timing purposes as shown above.
Please see https://github.com/AaronWatters/jp_proxy_widget and the discussion of asynchronicity of widgets in the Tutorial notebook.
Post a Comment for "Jupyter And Timer Functions?"