3

I was able to embed a bokeh server graph in Flask. This is the output on localhost:

enter image description here

Problem is I am not being able to make this work on Heroku. All I get displayed is the text "Here is your great site".

So, the app is made of three files.

There's the script containing the graph:

#bokeh_plot.py
import pandas as pd

from bokeh.layouts import row, widgetbox
from bokeh.models import Select
from bokeh.palettes import Spectral5
from bokeh.plotting import curdoc, figure
from bokeh.sampledata.autompg import autompg

df = autompg.copy()

SIZES = list(range(6, 22, 3))
COLORS = Spectral5
ORIGINS = ['North America', 'Europe', 'Asia']

# data cleanup
df.cyl = [str(x) for x in df.cyl]
df.origin = [ORIGINS[x-1] for x in df.origin]

df['year'] = [str(x) for x in df.yr]
del df['yr']

df['mfr'] = [x.split()[0] for x in df.name]
df.loc[df.mfr=='chevy', 'mfr'] = 'chevrolet'
df.loc[df.mfr=='chevroelt', 'mfr'] = 'chevrolet'
df.loc[df.mfr=='maxda', 'mfr'] = 'mazda'
df.loc[df.mfr=='mercedes-benz', 'mfr'] = 'mercedes'
df.loc[df.mfr=='toyouta', 'mfr'] = 'toyota'
df.loc[df.mfr=='vokswagen', 'mfr'] = 'volkswagen'
df.loc[df.mfr=='vw', 'mfr'] = 'volkswagen'
del df['name']

columns = sorted(df.columns)
discrete = [x for x in columns if df[x].dtype == object]
continuous = [x for x in columns if x not in discrete]
quantileable = [x for x in continuous if len(df[x].unique()) > 20]


def create_figure():
    xs = df[x.value].values
    ys = df[y.value].values
    x_title = x.value.title()
    y_title = y.value.title()

    kw = dict()
    if x.value in discrete:
        kw['x_range'] = sorted(set(xs))
    if y.value in discrete:
        kw['y_range'] = sorted(set(ys))
    kw['title'] = "%s vs %s" % (x_title, y_title)

    p = figure(plot_height=600, plot_width=800, tools='pan,box_zoom,reset', **kw)
    p.xaxis.axis_label = x_title
    p.yaxis.axis_label = y_title

    if x.value in discrete:
        p.xaxis.major_label_orientation = pd.np.pi / 4

    sz = 9
    if size.value != 'None':
        groups = pd.qcut(df[size.value].values, len(SIZES))
        sz = [SIZES[xx] for xx in groups.codes]

    c = "#31AADE"
    if color.value != 'None':
        groups = pd.qcut(df[color.value].values, len(COLORS))
        c = [COLORS[xx] for xx in groups.codes]
    p.circle(x=xs, y=ys, color=c, size=sz, line_color="white", alpha=0.6, hover_color='white', hover_alpha=0.5)

    return p


def update(attr, old, new):
    layout.children[1] = create_figure()


x = Select(title='X-Axis', value='mpg', options=columns)
x.on_change('value', update)

y = Select(title='Y-Axis', value='hp', options=columns)
y.on_change('value', update)

size = Select(title='Size', value='None', options=['None'] + quantileable)
size.on_change('value', update)

color = Select(title='Color', value='None', options=['None'] + quantileable)
color.on_change('value', update)

controls = widgetbox([x, y, color, size], width=200)
layout = row(controls, create_figure())

curdoc().add_root(layout)
curdoc().title = "Crossfilter"

The Flask script:

#app.py
import subprocess
import atexit
from flask import render_template, render_template_string, Flask
from bokeh.embed import autoload_server
from bokeh.client import pull_session

app = Flask(__name__)

bokeh_process = subprocess.Popen(
    ['bokeh', 'serve','--allow-websocket-origin=localhost:5000','bokeh_plot.py'], stdout=subprocess.PIPE)

@atexit.register
def kill_server():
    bokeh_process.kill()

@app.route("/")
def index():
    session=pull_session(app_path="/bokeh_plot")
    bokeh_script=autoload_server(None,app_path="/bokeh_plot",session_id=session.id)
    return render_template("index.html", bokeh_script=bokeh_script)

if __name__ == "__main__":
    print("STARTED")
    app.run(debug=True)

And the index.html template:

<!DOCTYPE html>
<html lang="en">
    <head>
        <style>
            @import url(https://fonts.googleapis.com/css?family=Noto+Sans);
            body {
              font-family: 'Noto Sans', sans-serif;
              -webkit-font-smoothing: antialiased;
              text-rendering: optimizeLegibility;
              color: #fff;
              background: #2F2F2F;
             }
        </style>
        <meta charset="utf-8">
        <title>Bokeh Crossfilter Example</title>
    </head>
    <body>
      <p> This is your great site<p>
      <div class="bk-root">
        {{ bokeh_script|safe }}
      </div>
    </body>
</html>

And this is what I get from the heroku logs. Note there's an Cannot start Bokeh server, port 5006 is already in use" line there.

heroku[web.1]: State changed from down to starting
heroku[web.1]: Unidling
heroku[web.1]: Starting process with command `gunicorn app:app`
app[web.1]: [2016-07-25 09:32:40 +0000] [3] [INFO] Starting gunicorn 19.6.0
app[web.1]: [2016-07-25 09:32:40 +0000] [3] [INFO] Listening at: http://0.0.0.0:48905 (3)
app[web.1]: [2016-07-25 09:32:40 +0000] [3] [INFO] Using worker: sync
app[web.1]: [2016-07-25 09:32:40 +0000] [7] [INFO] Booting worker with pid: 7
app[web.1]: [2016-07-25 09:32:40 +0000] [8] [INFO] Booting worker with pid: 8
heroku[web.1]: State changed from starting to up
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/app.py"", line 1641, in full_dispatch_request"
app[web.1]: Traceback (most recent call last):
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/app.py"", line 1988, in wsgi_app"
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/app.py"", line 1544, in handle_user_exception"
app[web.1]:     rv = self.handle_user_exception(e)
"app[web.1]: [2016-07-25 09:32:44,050] ERROR in app: Exception on / [GET]"
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/_compat.py"", line 33, in reraise"
app[web.1]:     response = self.full_dispatch_request()
"app[web.1]:     reraise(exc_type, exc_value, tb)"
app[web.1]:     raise value
"app[web.1]: OSError: Cannot pull session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)"
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/app.py"", line 1639, in full_dispatch_request"
app[web.1]:     rv = self.dispatch_request()
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/app.py"", line 1625, in dispatch_request"
app[web.1]:     return self.view_functions[rule.endpoint](**req.view_args)
"app[web.1]:   File ""/app/app.py"", line 37, in index"
"app[web.1]:     session=pull_session(app_path=""/bokeh_plot"")"
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/bokeh/client/session.py"", line 112, in pull_session"
app[web.1]:     session.pull()
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/bokeh/client/session.py"", line 231, in pull"
app[web.1]:     rv = self.handle_user_exception(e)
"app[web.1]:     raise IOError(""Cannot pull session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)"")"
app[web.1]: ERROR:app:Exception on / [GET]
app[web.1]: Traceback (most recent call last):
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/app.py"", line 1988, in wsgi_app"
app[web.1]:     response = self.full_dispatch_request()
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/app.py"", line 1641, in full_dispatch_request"
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/_compat.py"", line 33, in reraise"
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/app.py"", line 1625, in dispatch_request"
app[web.1]:     raise value
app[web.1]:     rv = self.dispatch_request()
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/app.py"", line 1639, in full_dispatch_request"
app[web.1]:     return self.view_functions[rule.endpoint](**req.view_args)
"app[web.1]:   File ""/app/app.py"", line 37, in index"
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/flask/app.py"", line 1544, in handle_user_exception"
"app[web.1]:     reraise(exc_type, exc_value, tb)"
"app[web.1]:     session=pull_session(app_path=""/bokeh_plot"")"
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/bokeh/client/session.py"", line 112, in pull_session"
app[web.1]:     session.pull()
"app[web.1]:   File ""/app/.heroku/python/lib/python3.5/site-packages/bokeh/client/session.py"", line 231, in pull"
"app[web.1]:     raise IOError(""Cannot pull session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)"")"
"app[web.1]: OSError: Cannot pull session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)"
"heroku[router]: at=info method=GET path=""/"" host=bokehapp.herokuapp.com request_id=f60be826-3fba-4eab-b18f-aa0eb822ebdd fwd=""217.73.139.64"" dyno=web.1 connect=2ms service=77ms status=500 bytes=456"
"app[web.1]: 2016-07-25 09:32:44,637 Starting Bokeh server on port 5006 with applications at paths ['/bokeh_plot']"
**"app[web.1]: 2016-07-25 09:32:44,683 Cannot start Bokeh server, port 5006 is already in use"**
"app[web.1]: 2016-07-25 09:32:44,681 Starting Bokeh server version 0.12.0"
"app[web.1]: 2016-07-25 09:32:44,637 Starting Bokeh server with process id: 26"
"app[web.1]: 2016-07-25 09:32:44,620 Starting Bokeh server version 0.12.0"
"app[web.1]: 2016-07-25 09:32:55,074 WebSocket connection opened"
"app[web.1]: 2016-07-25 09:32:55,187 ServerConnection created"
"heroku[router]: at=info method=GET path=""/"" host=bokehapp.herokuapp.com request_id=41493fd5-aed9-4198-b063-652f93cee49e fwd=""217.73.139.64"" dyno=web.1 connect=0ms service=550ms status=200 bytes=1066"

I have desperately searched for an answer on the web, but haven't found anything on how to deploy a flask app that contains a bokeh server app inside. So, this post could be a good resource if anyone is able to provide an answer.

I believe the key is in the subprocess line in the app.py file where the bokeh server is called, but my knowledge in web services is limited so, can't figure out how to make it work. Any idea?

Edit 1: bigreddot suggested to change the value of --allow-websocket-origin to the url of the app. So, I did change localhost:5000 to bokehapp.herokuapp.com. That seems to fix the IOError: Cannot put session document. However, the graph still doesn't show. Here are the new logs I get from Heroku:

heroku[slug-compiler]: Slug compilation finished
heroku[slug-compiler]: Slug compilation started
heroku[web.1]: State changed from down to starting
heroku[web.1]: Starting process with command `gunicorn app:app`
app[web.1]: [2016-07-25 15:02:50 +0000] [3] [INFO] Using worker: sync
app[web.1]: [2016-07-25 15:02:50 +0000] [7] [INFO] Booting worker with pid: 7
app[web.1]: [2016-07-25 15:02:50 +0000] [3] [INFO] Starting gunicorn 19.6.0
app[web.1]: [2016-07-25 15:02:50 +0000] [3] [INFO] Listening at: http://0.0.0.0:23620 (3)
app[web.1]: [2016-07-25 15:02:50 +0000] [8] [INFO] Booting worker with pid: 8
heroku[api]: Release v7 created by adiadi@gmail.com
heroku[api]: Deploy be12fcc by adiadi@gmail.com
heroku[web.1]: State changed from starting to up
"app[web.1]: 2016-07-25 15:02:55,278 Starting Bokeh server with process id: 25"
"app[web.1]: 2016-07-25 15:02:55,261 Starting Bokeh server version 0.12.0"
"app[web.1]: 2016-07-25 15:02:55,276 Starting Bokeh server version 0.12.0"
"app[web.1]: 2016-07-25 15:02:55,284 Cannot start Bokeh server, port 5006 is already in use"
"app[web.1]: 2016-07-25 15:02:55,278 Starting Bokeh server on port 5006 with applications at paths ['/bokeh_plot']"
"app[web.1]: 2016-07-25 15:03:14,375 WebSocket connection opened"
"app[web.1]: 2016-07-25 15:03:15,029 ServerConnection created"
"heroku[router]: at=info method=GET path=""/"" host=bokehapp.herokuapp.com request_id=5e7a06ad-4526-4304-b00e-0c37979ab751 fwd=""109.236.33.234"" dyno=web.1 connect=1ms service=3778ms status=200 bytes=1066"
"app[web.1]: 2016-07-25 15:03:59,253 ServerConnection created"
"app[web.1]: 2016-07-25 15:03:59,133 WebSocket connection opened"

Edit 2: Some even more logs after passing --log-level=debug to subprocess:

heroku[slug-compiler]: Slug compilation started
heroku[slug-compiler]: Slug compilation finished
heroku[api]: Deploy 9c2fefa by adiadi@gmail.com
heroku[api]: Release v12 created by adiadi@gmail.com
heroku[web.1]: Restarting
heroku[web.1]: State changed from up to starting
heroku[web.1]: Stopping all processes with SIGTERM
app[web.1]: [2016-07-25 21:53:37 +0000] [3] [INFO] Handling signal: term
app[web.1]: [2016-07-25 21:53:37 +0000] [7] [INFO] Worker exiting (pid: 7)
app[web.1]: [2016-07-25 21:53:38 +0000] [3] [INFO] Shutting down: Master
app[web.1]: [2016-07-25 21:53:37 +0000] [8] [INFO] Worker exiting (pid: 8)
heroku[web.1]: Process exited with status 0
heroku[web.1]: Starting process with command `gunicorn app:app`
app[web.1]: [2016-07-25 21:53:53 +0000] [3] [INFO] Starting gunicorn 19.6.0
app[web.1]: [2016-07-25 21:53:53 +0000] [3] [INFO] Using worker: sync
app[web.1]: [2016-07-25 21:53:53 +0000] [8] [INFO] Booting worker with pid: 8
app[web.1]: [2016-07-25 21:53:53 +0000] [7] [INFO] Booting worker with pid: 7
app[web.1]: [2016-07-25 21:53:53 +0000] [3] [INFO] Listening at: http://0.0.0.0:41934 (3)
heroku[web.1]: State changed from starting to up
"app[web.1]: 2016-07-25 21:53:58,821 Allowed Host headers: ['localhost:5006']"
"app[web.1]: 2016-07-25 21:53:58,821 These host origins can connect to the websocket: ['bokehapp.herokuapp.com:80', 'localhost:5006']"
"app[web.1]: 2016-07-25 21:53:58,821 Patterns are:"
"app[web.1]: 2016-07-25 21:53:58,821 Starting Bokeh server version 0.12.0"
"app[web.1]: 2016-07-25 21:53:58,823     {'application_context': <bokeh.server.application_context.ApplicationContext object at 0x7f7bf7dd51d0>,"
"app[web.1]: 2016-07-25 21:53:58,832     <class 'bokeh.server.views.ws.WSHandler'>,"
"app[web.1]: 2016-07-25 21:53:58,832    ('/bokeh_plot/autoload.js',"
"app[web.1]: 2016-07-25 21:53:58,831    ('/bokeh_plot/ws',"
"app[web.1]: 2016-07-25 21:53:58,832     <class 'bokeh.server.views.autoload_js_handler.AutoloadJsHandler'>,"
"app[web.1]: 2016-07-25 21:53:58,832     {'application_context': <bokeh.server.application_context.ApplicationContext object at 0x7f7bf7dd51d0>,"
"app[web.1]: 2016-07-25 21:53:58,832      'bokeh_websocket_path': '/bokeh_plot/ws'}),"
"app[web.1]: 2016-07-25 21:53:58,833     {'applications': {'/bokeh_plot': <bokeh.server.application_context.ApplicationContext object at 0x7f7bf7dd51d0>},"
"app[web.1]: 2016-07-25 21:53:58,823   [('/bokeh_plot/?',"
"app[web.1]: 2016-07-25 21:53:58,823     <class 'bokeh.server.views.doc_handler.DocHandler'>,"
"app[web.1]: 2016-07-25 21:53:58,823      'bokeh_websocket_path': '/bokeh_plot/ws'}),"
"app[web.1]: 2016-07-25 21:53:58,832     {'application_context': <bokeh.server.application_context.ApplicationContext object at 0x7f7bf7dd51d0>,"
"app[web.1]: 2016-07-25 21:53:58,833      'prefix': '',"
"app[web.1]: 2016-07-25 21:53:58,833      'use_redirect': True}),"
"app[web.1]: 2016-07-25 21:53:58,833    ('/static/(.*)',"
"app[web.1]: 2016-07-25 21:53:58,833     <class 'bokeh.server.views.static_handler.StaticHandler'>)]"
"app[web.1]: 2016-07-25 21:53:58,832      'bokeh_websocket_path': '/bokeh_plot/ws'}),"
"app[web.1]: 2016-07-25 21:53:58,861 Starting Bokeh server on port 5006 with applications at paths ['/bokeh_plot']"
"app[web.1]: 2016-07-25 21:53:58,832    ('/?',"
"app[web.1]: 2016-07-25 21:53:58,833     <class 'bokeh.server.views.root_handler.RootHandler'>,"
"app[web.1]: 2016-07-25 21:53:58,896 These host origins can connect to the websocket: ['bokehapp.herokuapp.com:80', 'localhost:5006']"
"app[web.1]: 2016-07-25 21:53:58,898   [('/bokeh_plot/?',"
"app[web.1]: 2016-07-25 21:53:58,899     {'application_context': <bokeh.server.application_context.ApplicationContext object at 0x7f8a84cb4b70>,"
"app[web.1]: 2016-07-25 21:53:58,896 Starting Bokeh server version 0.12.0"
"app[web.1]: 2016-07-25 21:53:58,897 Patterns are:"
"app[web.1]: 2016-07-25 21:53:58,899     <class 'bokeh.server.views.doc_handler.DocHandler'>,"
"app[web.1]: 2016-07-25 21:53:58,896 Allowed Host headers: ['localhost:5006']"
"app[web.1]: 2016-07-25 21:53:58,900     <class 'bokeh.server.views.autoload_js_handler.AutoloadJsHandler'>,"
"app[web.1]: 2016-07-25 21:53:58,899    ('/bokeh_plot/ws',"
"app[web.1]: 2016-07-25 21:53:58,899     <class 'bokeh.server.views.ws.WSHandler'>,"
"app[web.1]: 2016-07-25 21:53:58,899      'bokeh_websocket_path': '/bokeh_plot/ws'}),"
"app[web.1]: 2016-07-25 21:53:58,899     {'application_context': <bokeh.server.application_context.ApplicationContext object at 0x7f8a84cb4b70>,"
"app[web.1]: 2016-07-25 21:53:58,900      'bokeh_websocket_path': '/bokeh_plot/ws'}),"
"app[web.1]: 2016-07-25 21:53:58,900    ('/bokeh_plot/autoload.js',"
"app[web.1]: 2016-07-25 21:53:58,861 Starting Bokeh server with process id: 25"
"app[web.1]: 2016-07-25 21:53:58,900     {'application_context': <bokeh.server.application_context.ApplicationContext object at 0x7f8a84cb4b70>,"
"app[web.1]: 2016-07-25 21:53:58,900      'bokeh_websocket_path': '/bokeh_plot/ws'}),"
"app[web.1]: 2016-07-25 21:53:58,901      'use_redirect': True}),"
"app[web.1]: 2016-07-25 21:53:58,900    ('/?',"
"app[web.1]: 2016-07-25 21:53:58,901    ('/static/(.*)',"
"app[web.1]: 2016-07-25 21:53:58,901     <class 'bokeh.server.views.static_handler.StaticHandler'>)]"
"app[web.1]: 2016-07-25 21:53:58,904 Cannot start Bokeh server, port 5006 is already in use"
"app[web.1]: 2016-07-25 21:53:58,900     <class 'bokeh.server.views.root_handler.RootHandler'>,"
"app[web.1]: 2016-07-25 21:53:58,901     {'applications': {'/bokeh_plot': <bokeh.server.application_context.ApplicationContext object at 0x7f8a84cb4b70>},"
"app[web.1]: 2016-07-25 21:53:58,901      'prefix': '',"
"app[web.1]: 2016-07-25 21:54:13,880 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:54:13,880 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:54:43,870 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:54:43,869 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:54:58,870 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:54:58,869 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:55:13,862 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:55:13,862 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:55:28,864 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:55:28,863 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:55:43,864 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:55:43,865 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:55:58,862 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:55:58,862 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:56:13,876 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:56:13,877 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:56:28,864 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:56:28,865 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:56:43,875 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:56:43,876 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:56:58,872 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:56:58,872 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:57:13,863 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:57:13,862 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:57:28,872 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:57:28,872 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:57:43,868 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:57:43,867 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:57:58,863 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:57:58,864 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:58:13,879 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:58:13,880 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:58:28,873 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:58:28,874 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:58:43,872 [pid 25]   /bokeh_plot has 0 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:58:43,871 [pid 25] 0 clients connected"
"app[web.1]: 2016-07-25 21:58:49,718 WebSocket connection opened"
"app[web.1]: 2016-07-25 21:58:50,223 Sending pull-doc-reply from session 'Q4LGpWidke5G85sboBiRPMazzPfwOwTDMirNrDsTY3OL'"
"app[web.1]: 2016-07-25 21:58:50,177 Receiver created for Protocol('1.0')"
"app[web.1]: 2016-07-25 21:58:50,178 ServerHandler created for Protocol('1.0')"
"app[web.1]: 2016-07-25 21:58:50,178 ServerConnection created"
"heroku[router]: at=info method=GET path=""/"" host=bokehapp.herokuapp.com request_id=15fc6908-1031-4d88-86cc-8048d6195a6f fwd=""109.236.47.207"" dyno=web.1 connect=1ms service=1341ms status=200 bytes=1066"
"app[web.1]: 2016-07-25 21:58:58,864 [pid 25]   /bokeh_plot has 1 sessions with 0 unused"
"app[web.1]: 2016-07-25 21:58:58,863 [pid 25] 1 clients connected"
multigoodverse
  • 7,638
  • 19
  • 64
  • 106
  • 1
    Well one issue is that `allow-websocket-origin` tells the Bokeh server that it's OK to initiate websocket connections that originate from "somewhere else" (i.e. someone hitting the Bokeh server via an embedded webpage instead og navigating directly to the Bokeh server). No one will *ever* be originating from `localhost` so that value can't be right. It should be the public ip/hostname that people will navigate to to see your flask app page. – bigreddot Jul 25 '16 at 13:32
  • There might be other issues, it is hard to diagnose without also seeing the Bokeh server logs too. – bigreddot Jul 25 '16 at 13:33
  • @bigreddot thanks so much. I changed `localhost:5000` to `bokehapp.herokuapp.com` which is the url for the app. That got rid of the `IOError: Cannot pull session document`. It also got rid of the internal server error which I was getting I visited bokehapp.herokuapp.com. However, the graph is still not showing on the webpage. I am not sure where to see the Bokeh server logs. I am only aware of the heroku logs command. I edited the question to show the latest logs after your proposed changes. Would be great if you showed me how to diagnose this even further. – multigoodverse Jul 25 '16 at 15:15
  • Can you confirm that the subprocess is executing in the correct location. I suppose this would mean that `bokeh_plot.py` in the same directory that `app.py` is being executed. Also, there may be issues running multiple processes with gunicorn -- i think this may mean multiple subprocess calls – quasiben Jul 25 '16 at 19:21
  • Your new output seems to be capturing the Bokeh server console output. Lines like: `2016-07-25 15:02:55,278 Starting Bokeh server with process id: 25` are Bokeh server logs. It says a connection is opened but reports no error. What is in the browser JavaScript console log? Also you can start the server with `--log-level=debug` and it will provide more verbose logging which might be helpful. – bigreddot Jul 25 '16 at 20:39
  • I also just noticed this: `Cannot start Bokeh server, port 5006 is already in use` are you trying to start Bokeh server twice? If so, the two instances need to be on distinct ports. – bigreddot Jul 25 '16 at 20:39
  • @bigreddot yes, bokeh_plot.py and app.py are in the same directory. In Procfile I have `web: gunicorn app:app`. I added `--logs-level=debug` and I added the logs to my original question if you'd want to take a look. Regarding ports, I am not sure what Heroku uses, but locally bokeh server runs on port 5006 and Flask runs on 5000. There's an answer posted here (http://stackoverflow.com/a/38447618/1585017) recently about deploying bokeh and heroku. The last comment suggests there might be two web workers there. Does that mean I need to add another line to my Procfile pointing to Bokeh server? – multigoodverse Jul 25 '16 at 22:11
  • I added a line to Procfile and now Procfile looks like `web: gunicorn app:app web: bokeh serve --port=$PORT --host=bokehapp.herokuapp.com --host=* --address=0.0.0.0 --use-xheaders bokeh_plot.py ` That successfully shows the graph on https://bokehapp.herokuapp.com/bokeh_plot, but it doesn't show the content served by Flask. – multigoodverse Jul 26 '16 at 09:34
  • 2
    @multigoodverse did you ever get this figured out? – Eric Valente Jan 02 '19 at 03:29

1 Answers1

-1

Please check this link

The author suggested using Bokeh components method to generate script that will be embedded into the .html template.

Not sure whether it still needs two web workers though, since I am trying to make my app work on Heroku too.

Ralf
  • 16,086
  • 4
  • 44
  • 68
Qing
  • 1
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – mbomb007 Jan 20 '17 at 21:29