Integrate bokeh server with an asyncio API

I have an API that retrieve financial data using asyncio. I am trying to integrate it with bokeh atm.

I simplified the behavior of the asyncio API to demonstrate my problem here, but basically lets consider that it retrieve some data and want to plot i every second like so:

from bokeh.models import ColumnDataSource
from bokeh.client import push_session
from bokeh.plotting import figure, curdoc

import asyncio
import numpy as np

x=0;y=0

async def udpate_data():
while True:
await asyncio.sleep(1)
global x,y
x+=1; y+=np.sin(x)
print(x)
source.stream(dict(x=,y=[y]))

source=ColumnDataSource(dict(x=,y=))
p=figure()
l=p.line(x=“x”,y=“y”,source=source)
session=push_session(curdoc(),session_id=“main”)
session.show(p)

loop=asyncio.get_event_loop()
loop.run_until_complete(udpate_data())

``

This is from an example on how to integrate bokeh and asyncio that I found here:

http://blog.angryturtle.com/2017/04/realtime-bokeh-plotting-with-asyncio.html

https://gist.github.com/sonium0/65cde09ec21d573281d1ce2ca33a6262

However, if i try to run the script (for instance saving it in /bokeh_test/main.py and running it from ../ as bokeh serve bokeh_test at first it seems like working as the shell displays:

2017-10-31 18:34:36,871 Starting Bokeh server version 0.12.10 (running on Tornado 4.5.2)
2017-10-31 18:34:36,873 Bokeh app running at: http://localhost:5006/bokeh
2017-10-31 18:34:36,873 Starting Bokeh server with process id: 1711

``

However if i go to my browser and try to connect to http://localhost:5006/bokeh, I receive error

2017-10-31 18:35:13,141 Failed to connect to server: HTTP 599: Timeout during request
2017-10-31 18:35:13,143 Error running application handler <bokeh.application.handlers.directory.DirectoryHandler object at 0x7f543dc50eb8>: Cannot p$
sh session document because we failed to connect to the server (to start the server, try the ‘bokeh serve’ command)
File “session.py”, line 370, in push:
raise IOError(“Cannot push session document because we failed to connect to the server (to start the server, try the ‘bokeh serve’ command)”) Traceba
ck (most recent call last):
File “/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/application/handlers/code_runner.py”, line 125, in run
exec(self._code, module.dict)
File “/home/depot/wintergreen/test_scripts/bokeh3/main.py”, line 20, in
session=push_session(curdoc(),session_id=“main”)
File “/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/util/api.py”, line 190, in wrapper
return obj(*args, **kw)
File “/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/client/session.py”, line 161, in push_session
session.push(document)
File “/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/util/api.py”, line 190, in wrapper
return obj(*args, **kw)
File “/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/client/session.py”, line 370, in push
raise IOError(“Cannot push session document because we failed to connect to the server (to start the server, try the ‘bokeh serve’ command)”)
OSError: Cannot push session document because we failed to connect to the server (to start the server, try the ‘bokeh serve’ command)

``

I am a beginner programmer and unfamiliar with asyncio and tornado. I do not want to convert my existing app to tornado as it is quite developed already.

Thank you for your help,

Best,

Vincent

Hi,

There's a lot of misunderstanding evident in the code below, and the intended usage is also vague, so it's hard for me to know how to start advising. First I'd suggest studying these sections:

  bokeh.server — Bokeh 3.3.2 Documentation

  http://bokeh.pydata.org/en/latest/docs/user_guide/server.html

The first thing to note: when you run "bokeh serve app.py" the bokeh server runs the code in "app.py" on *every single connection*. Every connection requires its own new Document, and the code in "app.py" is what should generate that Document. An immediate corrollary is that blocking functions like "loop.run_until_complete" should never be run in "app.py". Nor should bokeh.client functions like "push_session". The latter is for connecting outside python processes to a separate running Bokeh server. They are not for use by code running *in* a Bokeh server.

Your best bet may be to embed a Bokeh server as a library:

  Bokeh server — Bokeh 3.3.2 Documentation

It may even be possible to use the asyncio event loop instead of a Tornado IOLoop, but I don't actually know enough about asyncio to say for sure. If not perhaps one or the other loops can be run in a thread from a lifecycle callback:

  Bokeh server — Bokeh 3.3.2 Documentation

Bryan

···

On Oct 31, 2017, at 14:00, [email protected] wrote:

I have an API that retrieve financial data using asyncio. I am trying to integrate it with bokeh atm.

I simplified the behavior of the asyncio API to demonstrate my problem here, but basically lets consider that it retrieve some data and want to plot i every second like so:

from bokeh.models import ColumnDataSource
from bokeh.client import push_session
from bokeh.plotting import figure, curdoc

import asyncio
import numpy as np

x=0;y=0

async def udpate_data():
    while True:
        await asyncio.sleep(1)
        global x,y
        x+=1; y+=np.sin(x)
        print(x)
        source.stream(dict(x=,y=[y]))

source=ColumnDataSource(dict(x=,y=))
p=figure()
l=p.line(x="x",y="y",source=source)
session=push_session(curdoc(),session_id="main")
session.show(p)
        
loop=asyncio.get_event_loop()
loop.run_until_complete(udpate_data())

This is from an example on how to integrate bokeh and asyncio that I found here:
http://blog.angryturtle.com/2017/04/realtime-bokeh-plotting-with-asyncio.html
https://gist.github.com/sonium0/65cde09ec21d573281d1ce2ca33a6262

However, if i try to run the script (for instance saving it in `/bokeh_test/main.py` and running it from `../` as `bokeh serve bokeh_test` at first it seems like working as the shell displays:
2017-10-31 18:34:36,871 Starting Bokeh server version 0.12.10 (running on Tornado 4.5.2)
2017-10-31 18:34:36,873 Bokeh app running at: http://localhost:5006/bokeh
2017-10-31 18:34:36,873 Starting Bokeh server with process id: 1711

However if i go to my browser and try to connect to http://localhost:5006/bokeh, I receive error
2017-10-31 18:35:13,141 Failed to connect to server: HTTP 599: Timeout during request
2017-10-31 18:35:13,143 Error running application handler <bokeh.application.handlers.directory.DirectoryHandler object at 0x7f543dc50eb8>: Cannot p$
sh session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)
File "session.py", line 370, in push:
raise IOError("Cannot push session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)") Traceba
ck (most recent call last):
  File "/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/application/handlers/code_runner.py", line 125, in run
    exec(self._code, module.__dict__)
  File "/home/depot/wintergreen/test_scripts/bokeh3/main.py", line 20, in <module>
    session=push_session(curdoc(),session_id="main")
  File "/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/util/api.py", line 190, in wrapper
    return obj(*args, **kw)
  File "/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/client/session.py", line 161, in push_session
    session.push(document)
  File "/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/util/api.py", line 190, in wrapper
    return obj(*args, **kw)
  File "/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/client/session.py", line 370, in push
    raise IOError("Cannot push session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)")
OSError: Cannot push session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)

I am a beginner programmer and unfamiliar with asyncio and tornado. I do not want to convert my existing app to tornado as it is quite developed already.

Thank you for your help,

Best,

Vincent

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/06ab27f5-bb9a-44b0-b84b-9aaf804d7e33%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

You run the client in wrong way.

The bokeh client should run in follow steps like :

  1. bokeh serve #start the server

  2. python main.py . # it will send plot server ,and push the datat to serve realtime.

bokeh serve bokeh_test is for running bokeh applicaton in server.

···

On Wednesday, November 1, 2017 at 3:31:32 AM UTC+8, vincent konate wrote:

I have an API that retrieve financial data using asyncio. I am trying to integrate it with bokeh atm.

I simplified the behavior of the asyncio API to demonstrate my problem here, but basically lets consider that it retrieve some data and want to plot i every second like so:

from bokeh.models import ColumnDataSource
from bokeh.client import push_session
from bokeh.plotting import figure, curdoc

import asyncio
import numpy as np

x=0;y=0

async def udpate_data():
while True:
await asyncio.sleep(1)
global x,y
x+=1; y+=np.sin(x)
print(x)
source.stream(dict(x=,y=[y]))

source=ColumnDataSource(dict(x=,y=))
p=figure()
l=p.line(x=“x”,y=“y”,source=source)
session=push_session(curdoc(),session_id=“main”)
session.show(p)

loop=asyncio.get_event_loop()
loop.run_until_complete(udpate_data())

``

This is from an example on how to integrate bokeh and asyncio that I found here:

http://blog.angryturtle.com/2017/04/realtime-bokeh-plotting-with-asyncio.html

https://gist.github.com/sonium0/65cde09ec21d573281d1ce2ca33a6262

However, if i try to run the script (for instance saving it in /bokeh_test/main.py and running it from ../ as bokeh serve bokeh_test at first it seems like working as the shell displays:

2017-10-31 18:34:36,871 Starting Bokeh server version 0.12.10 (running on Tornado 4.5.2)
2017-10-31 18:34:36,873 Bokeh app running at: http://localhost:5006/bokeh
2017-10-31 18:34:36,873 Starting Bokeh server with process id: 1711

``

However if i go to my browser and try to connect to http://localhost:5006/bokeh, I receive error

2017-10-31 18:35:13,141 Failed to connect to server: HTTP 599: Timeout during request
2017-10-31 18:35:13,143 Error running application handler <bokeh.application.handlers.directory.DirectoryHandler object at 0x7f543dc50eb8>: Cannot p$
sh session document because we failed to connect to the server (to start the server, try the ‘bokeh serve’ command)
File “session.py”, line 370, in push:
raise IOError(“Cannot push session document because we failed to connect to the server (to start the server, try the ‘bokeh serve’ command)”) Traceba
ck (most recent call last):
File “/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/application/handlers/code_runner.py”, line 125, in run
exec(self._code, module.dict)
File “/home/depot/wintergreen/test_scripts/bokeh3/main.py”, line 20, in
session=push_session(curdoc(),session_id=“main”)
File “/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/util/api.py”, line 190, in wrapper
return obj(*args, **kw)
File “/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/client/session.py”, line 161, in push_session
session.push(document)
File “/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/util/api.py”, line 190, in wrapper
return obj(*args, **kw)
File “/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/client/session.py”, line 370, in push
raise IOError(“Cannot push session document because we failed to connect to the server (to start the server, try the ‘bokeh serve’ command)”)
OSError: Cannot push session document because we failed to connect to the server (to start the server, try the ‘bokeh serve’ command)

``

I am a beginner programmer and unfamiliar with asyncio and tornado. I do not want to convert my existing app to tornado as it is quite developed already.

Thank you for your help,

Best,

Vincent

Hi,

However, please note that using the Bokeh server in this way, i.e. by starting a bare "bokeh serve" and using bokeh.client to run callbacks "externally" is officially discouraged in the strongest possible terms. It inherently more fragile and less performant. We only support use cases where the Bokeh server runs a app code directly, whether that's by running "bokeh serve app" or by programmatically embedding a Bokeh server in another script.

Bryan

···

On Sep 15, 2018, at 18:30, kkyon <[email protected]> wrote:

You run the client in wrong way.

The bokeh client should run in follow steps like :

1. bokeh serve #start the server
2. python main.py . # it will send plot server ,and push the datat to serve realtime.

`bokeh serve bokeh_test` is for running bokeh applicaton in server.

On Wednesday, November 1, 2017 at 3:31:32 AM UTC+8, vincent konate wrote:
I have an API that retrieve financial data using asyncio. I am trying to integrate it with bokeh atm.

I simplified the behavior of the asyncio API to demonstrate my problem here, but basically lets consider that it retrieve some data and want to plot i every second like so:

from bokeh.models import ColumnDataSource
from bokeh.client import push_session
from bokeh.plotting import figure, curdoc

import asyncio
import numpy as np

x=0;y=0

async def udpate_data():
    while True:
        await asyncio.sleep(1)
        global x,y
        x+=1; y+=np.sin(x)
        print(x)
        source.stream(dict(x=,y=[y]))

source=ColumnDataSource(dict(x=,y=))
p=figure()
l=p.line(x="x",y="y",source=source)
session=push_session(curdoc(),session_id="main")
session.show(p)
        
loop=asyncio.get_event_loop()
loop.run_until_complete(udpate_data())

This is from an example on how to integrate bokeh and asyncio that I found here:
http://blog.angryturtle.com/2017/04/realtime-bokeh-plotting-with-asyncio.html
https://gist.github.com/sonium0/65cde09ec21d573281d1ce2ca33a6262

However, if i try to run the script (for instance saving it in `/bokeh_test/main.py` and running it from `../` as `bokeh serve bokeh_test` at first it seems like working as the shell displays:
2017-10-31 18:34:36,871 Starting Bokeh server version 0.12.10 (running on Tornado 4.5.2)
2017-10-31 18:34:36,873 Bokeh app running at: http://localhost:5006/bokeh
2017-10-31 18:34:36,873 Starting Bokeh server with process id: 1711

However if i go to my browser and try to connect to http://localhost:5006/bokeh, I receive error
2017-10-31 18:35:13,141 Failed to connect to server: HTTP 599: Timeout during request
2017-10-31 18:35:13,143 Error running application handler <bokeh.application.handlers.directory.DirectoryHandler object at 0x7f543dc50eb8>: Cannot p$
sh session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)
File "session.py", line 370, in push:
raise IOError("Cannot push session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)") Traceba
ck (most recent call last):
  File "/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/application/handlers/code_runner.py", line 125, in run
    exec(self._code, module.__dict__)
  File "/home/depot/wintergreen/test_scripts/bokeh3/main.py", line 20, in <module>
    session=push_session(curdoc(),session_id="main")
  File "/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/util/api.py", line 190, in wrapper
    return obj(*args, **kw)
  File "/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/client/session.py", line 161, in push_session
    session.push(document)
  File "/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/util/api.py", line 190, in wrapper
    return obj(*args, **kw)
  File "/home/depot/.conda/envs/python36/lib/python3.6/site-packages/bokeh/client/session.py", line 370, in push
    raise IOError("Cannot push session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)")
OSError: Cannot push session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)

I am a beginner programmer and unfamiliar with asyncio and tornado. I do not want to convert my existing app to tornado as it is quite developed already.

Thank you for your help,

Best,

Vincent

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/526c6b4e-268b-401c-9cbe-bd5f485c7638%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Hi all,
Hijacking this topic as it seems to be relevant to my problem.
I’ve got a pre-existing asyncio loop generating data via events as well as awaiting a bunch of coroutines.
I’d like to monitor some of this data by sending it via doc.add_next_tick_callback() / source.stream() (defined in modify_doc(), not shown below).

I’ve already got a working solution, but I don’t have the skills to diagnose/understand whether the bokeh server / data stream will play nicely with the loop/other couroutines or if I should be worried about it being blocking to some degree, i.e. it is unclear for me what Tornado does with my original asyncio loop and how it is processed/used by bokeh.server.

from tornado.platform.asyncio import AsyncIOMainLoop
import tornado
from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
from bokeh.server.server import Server

# other library creates a asyncio loop
# define modify_doc() # happy to provide more details there

bokeh_app = Application(FunctionHandler(modify_doc))
AsyncIOMainLoop().install()
io_loop = tornado.ioloop.IOLoop.current()
server = Server({'/': bokeh_app}, io_loop=io_loop)
server.start()

if __name__ == '__main__':
    print('Opening Bokeh application on http://localhost:5006/')

    io_loop.add_callback(server.show, "/")
    io_loop.start()

Any help/alternative approach appreciated.
Best,
Louis

AFAIK Tornado overhead on the loop should be minimal. Bokeh callbacks will block while they are executing you might want to yield any long-running or expensive work from a thread pool executor or similar, if that is a concern.