☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Bokeh non-blocking task

Community Supportserver
huynguyen
huynguyen

I’m trying to update plots using asyncio. The structure of my callback is:

def periodic_plot_update():
    update_plot("", "", "")
    set_title("", "", "")

async def apc_cb():

    _ = await asyncio.wrap_future(
                executor.submit(periodic_plot_update), loop=None
            )
    doc.add_next_tick_callback(partial(self.dummy_update))

apc_cb.nolock = True

self.apc = doc.add_periodic_callback(
        apc_cb,
        5000,
)

In the update_plot function, I do data processing and update the column data source by cds.update(data=df). dummy_update is a print function to let me know the update was run. Now I’m having a RuntimeError: RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes. The error is at the cds.update step and I’m not sure why. Does anyone have any clue why? I did some small test, running print(“something”) inside the periodic_plot_update function, and it ran, but when involving the cds, it doesn’t.

Thank you,
H

⌁   Link to post
Bryan
Bryan

I don’t have any specific recollection of that, but I may just be forgetting. In any case, I don’t actually know, and haven’t ever tried to do what you are doing, so I think you will just have to experiment with without_document_lock and/or wrapping changes to Bokeh objects inside another add_next_tick_callback that your async function submits.

⌁   Link to post
Bryan
Bryan

It appears that was resolved here (for upcoming 3.0 release):

In the mean time the issue you link shows a workaround near the bottom.

⌁   Link to post
huynguyen
huynguyen

Yes. That was what I wrote in the original code. Blocking tasks such as sleep(longtime) work, but tasks regarding document updates (data update, plot title text setting,…) don’t work with this workaround.

⌁   Link to post
Bryan
Bryan

OK, well you still need to add another layer of callbacks. You need to put all code that changes Bokeh models in a callback of their own. Then use add_next_tick_callback on that from your async function. This is described in the docs I linked:

As with the thread example above, all actions that update document state must go through a next tick callback .

⌁   Link to post
Bryan
Bryan

I should add: there has been proposals to remove the document locking Bokeh does and in general make it play nicer with async. But this is a big task, I mostly only have enough enough async expertise to be a little dangerous, and definitely don’t (presently) have time/bandwidth. I would be happy to provide guidance or collaborate on this with a new contributor who has deep async expertise, and wants to dive into a non-trivial problem, though.

⌁   Link to post
huynguyen
huynguyen

So after tinkering for a bit, I got it to work by wrapping the update_plot function and set_title function inside the doc.add_next_tick_callback(fn).

def periodic_plot_update():
    doc.add_next_tick_callback(partial(update_plot,"", "", ""))
    doc.add_next_tick_callback(partial(set_title, "", "", ""))

async def apc_cb():
    _ = await asyncio.wrap_future(
                executor.submit(periodic_plot_update), loop=None
    )

apc_cb.nolock = True

self.apc = doc.add_periodic_callback(
        apc_cb,
        5000,
)

Now background tasks involving change of the document works without blocking.

Thank you Bryan for the suggestion.

⌁   Link to post

End of archived discussion · Replies are disabled