Hi,
I am developing a Bokeh-Embedded Flask app that needs to use a port other than 5006. As a minimum case, I modified the flask_embed.py example a bit (as attached below) to allow for using a different port, but the webpage cannot load the Bokeh plots if the port number is not 5006 - on the JS console it reads:
http://127.0.0.1:31051/bkapp/autoload.js?bokeh-autoload-element=4e079af1-8d05-497a-9ff0-71adb38aa39b Failed to load resource: net::ERR_CONNECTION_REFUSED
It seems that the Bokeh server refuses to connect the the Flask server when the port number is not 5006. Moreover, the returned script by autoload_server is embedded in the html with {{ script | safe}}. I feel the “safe” here may cause the problem, yet I’ve googling around but cannot solve the problem. Anyone kindly know how to deal with it?
Thanks,
Luyu
···
from flask import Flask, render_template
import numpy as np
from tornado.ioloop import IOLoop
from bokeh.application import Application
from bokeh.application.handlers import FunctionHandler
from bokeh.embed import autoload_server
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
from bokeh.server.server import Server
flask_app = Flask(name)
flask_host = “127.0.0.1:31050”
bokeh_host = “127.0.0.1:31051”
def modify_doc(doc):
x = np.linspace(0, 10, 1000)
y = np.log(x) * np.sin(x)
source = ColumnDataSource(data=dict(x=x, y=y))
plot = figure()
plot.line(‘x’, ‘y’, source=source)
slider = Slider(start=1, end=10, value=1, step=0.1)
def callback(attr, old, new):
y = np.log(x) * np.sin(x*new)
source.data = dict(x=x, y=y)
slider.on_change(‘value’, callback)
doc.add_root(column(slider, plot))
bokeh_app = Application(FunctionHandler(modify_doc))
io_loop = IOLoop.current()
server = Server({’/bkapp’: bokeh_app}, io_loop=io_loop, host=[bokeh_host], allow_websocket_origin=[flask_host, “127.0.0.1”])
server.start()
@flask_app.route(’/’, methods=[‘GET’])
def bkapp_page():
script = autoload_server(model=None, app_path=’/bkapp’, url=‘http://’+bokeh_host)
return render_template(“test.html”, script=script)
if name == ‘main’:
from tornado.httpserver import HTTPServer
from tornado.wsgi import WSGIContainer
from bokeh.util.browser import view
print(‘Opening Flask app with embedded Bokeh application on http://’+flask_host+’/’)
This uses Tornado to server the WSGI app that flask provides. Presumably the IOLoop
could also be started in a thread, and Flask could server its own app directly
http_server = HTTPServer(WSGIContainer(flask_app))
http_server.listen(address=flask_host.split(’:’)[0], port=flask_host.split(’:’)[1])
io_loop.add_callback(view, “http://”+flask_host+’/’)
io_loop.start()