Some thing like that, I readapted by using only localhost ip addresses and an example from panel’s doc.
in app.py
:
from bokeh.embed import server_document
from flask import Flask, render_template
def create_app():
app = Flask(__name__)
@app.route('/bokeh_app')
def bokeh_app():
script = server_document(f'http://127.0.0.1:5006/bokeh_app',
)
return render_template("embed.html", script=script)
return app
if __name__ == "__main__":
app = create_app()
app.run(debug=True, host="0.0.0.0", port=8080)
in bokeh_app.py
(using the sine example from the doc):
from app import create_app
import numpy as np
import param
import panel as pn
from tornado.ioloop import IOLoop
from bokeh.settings import settings
import panel as pn
settings.resources = 'inline'
#not sure if below are usefull
pn.config.js_files = {'tabulator': r'/static/js/tabulator.js',
'moment': r'/static/js/moment.js'}
pn.config.inline = True
class Sine(param.Parameterized):
phase = param.Number(default=0, bounds=(0, np.pi))
frequency = param.Number(default=1, bounds=(0.1, 2))
@param.depends('phase', 'frequency')
def view(self):
y = np.sin(np.linspace(0, np.pi * 3, 40) * self.frequency + self.phase)
y = ((y - y.min()) / y.ptp()) * 20
array = np.array(
[list((' ' * (int(round(d)) - 1) + '*').ljust(20)) for d in y])
return pn.pane.Str('\n'.join([''.join(r) for r in array.T]), height=380, width=500)
def bokehapp_doc(doc):
app = create_app()
with app.app_context():
sine = Sine(name='ASCII Sine Wave')
r = pn.Row(sine.param, sine.view).get_root()
doc.add_root(r)
if __name__ == "__main__":
server = Server({'/bokeh_app': bokehapp_doc,
},
io_loop=IOLoop(),
allow_websocket_origin=['127.0.0.1:5006',
'127.0.0.1:8080'],
)
server.start()
server.io_loop.start()
Then we start each file in a separate process
>> python app.py
>> python bokeh_app.py
Over the week-end I was having a slightly different approach, where app.py
was similar but I was just simply serving some panel example using panel serve
rather than building and editing a bokeh doc as in bokeh_app.py
.