Panel server embedded in Flask/gunicorn

Hi,

I have a bokeh server that is embedded in a Flask app under gunicorn. I want to migrate this to Panel ultimately, but have been unsuccessful finding details in the Server Deployment documentation or other examples of similar web server embedded deployments.

Using the bokeh Flask gunicorn embed app as proxy for a minimal example, I would appreciate any pointers on how to modify it as a reference example to map to my larger “real-world” problem.

Specifically, if I replace the bokeh column layout with a Panel Column and make it servable, what else needs to be done so that the resultant panel can be used in a web server?

#doc.add_root(column(slider, plot))
pnapp = pn.Column(slider, plot)
pnapp.servable()

Thanks in advance for any help.

Hi @_jm

According to Allow Serving Flask Apps PR one way to do it is

import panel as pn
from flask import Flask

flask_app = Flask(__name__)

@flask_app.route('/app')
def hello_world():
    return 'Hello, World!'

def panel_app():
    return "# This Panel app runs alongside flask, access the flask app at [here](./flask/app)"

pn.serve({'/flask': flask_app, 'panel': panel_app}, port=5001)

I believe you can find additional inspiration in

If you learn anything please, please share to make it easier for others to do as well.

You can share it here or even better as a contribution to the Panel documentation similar to the Django Apps documentation.

Thanks.

1 Like

@Marc

Thanks. I wanted to explicitly state my appreciation for the prompt and helpful feedback you have provided several times in the short time I have engaged the Panel discourse forum.

The Serving Flask Apps PR is fundamentally different than what I am trying to accomplish in that I have a bokeh server application that is embedded in Flask.

To migrate, I want to retain all of the low-level bokeh models and interactions but replace the layout with Panel equivalents (rows, columns, grids, tabs, etc.) to permit a more dynamic layout where I can add/remove elements from the layout.

It is straightforward to do this running the plain bokeh server and making all of the Panel layout items servable. The missing connection is how to best use these servable items in the Flask app code, which really needs to work with a bokeh document, which has a unique correspondence to each client session.

At first glance, your pointer to the Django Apps does indeed seem to provide the necessary inspiration. It at least allows me to serve the bokeh Flask gunicorn embedded server application with a Panel-based layout replacing the bokeh layout.

For reference, the Flask Gunicorn Embed example, flask_gunicorn_embed.by, can be modified by changing the bkapp() function to be the following. (The change is to comment-out the doc.add_root() and replace it with the panel layout and use the server_doc() method.)

CHANGES HIGHLIGHTED

#doc.add_root(column(slider, plot))
_col = pn.Column(slider, plot)
_col.server_doc(doc)

BKAPP FUNCTION

def bkapp(doc):
    df = sea_surface_temperature.copy()
    source = ColumnDataSource(data=df)

    plot = figure(x_axis_type='datetime', y_range=(0, 25), y_axis_label='Temperature (Celsius)',
                  title="Sea Surface Temperature at 43.18, -70.43")
    plot.line('time', 'temperature', source=source)

    def callback(attr, old, new):
        if new == 0:
            data = df
        else:
            data = df.rolling('{0}D'.format(new)).mean()
        source.data = ColumnDataSource.from_df(data)

    slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
    slider.on_change('value', callback)

    #doc.add_root(column(slider, plot))
    _col = pn.Column(slider, plot)
    _col.server_doc(doc)

    doc.theme = Theme(filename="theme.yaml")
1 Like