Adding lines to a multiline plot in a loop not working as expected

Hi,

I am trying to make a multiline plot which adds lines to the plot in a for loop, allowing the user to see the gradual addition of lines to the plot. I have attached an MRE:

import numpy as np
import time

from bokeh.plotting import figure, curdoc
from bokeh.layouts import row
from bokeh.models import ColumnDataSource, Button, Div


source = ColumnDataSource(
    {
        "units":[],
        "matches":[],
    }
)

simulation_plot = figure(
    height = 400,
    width = 400
)

simulation_plot_multilines = simulation_plot.multi_line(xs="matches", ys="units", source=source, line_color = "blue", line_width = 3)

matches = []
units = []

x = list(range(10))

def play():
    for i in range(10):
        matches.append(x)
        units.append(list(np.random.normal(size = 10)))
        source.stream(
            {
                "units":units,
                "matches": matches
            }, 
            rollover=i+1
        )
        print(source.data)
        time.sleep(5)
        
play_button = Button(label = "Play", width = 100, height =55)
play_button.on_click(play)

layout = row(play_button, Div(text = "", width = 100), simulation_plot)
curdoc().add_root(layout)

I do not know why but the lines all appear at once on the plot only once the loop has ended. This is weird to me as the data does get correctly streamed to the source as shown in the print statement. I would appreciate any help with this.

Thanks

@JackFrench2001 Synchronization requires exchanging network traffic between the Python and JavaScript runtimes and only happens at defined places. Specifically, state is synchronized when callback functions return, and not individually at every single property update inside the function.

One way to overcome this might be to wrap the “next” chunks of work up into lambdas or small functions, and pass those to curdoc().add_next_tick_callback so that those chunks of work actually occur in different callbacks, which will then trigger a synchronization when they complete.

Alternatively, Bokeh is able to schedule periodic callbacks directly via curdoc().add_periodic_callback, in case that is an option that works for your use case.