Flask-Bokeh-Gunicorn : Models must be owned by a single document
This is a piece of code to run the Flask application and the code inspired by the Bokeh server
flask_gunicorn_embed.py on Github .
At first it felt like a charm; However, after refreshing the page, this error occurs.
Models must be owned by only a single document: … (rest truncated)
By the way, the code is run using gunicorn
.
In addition, the create_figure()
function returns a layout
from Decision_Tree.Plot.decision_tree import create_figure
if __name__ == '__main__':
import sys
sys.exit()
app = Flask(__name__)
def modify_doc(doc):
# Create the plot
plot = create_figure()
# Embed plot into HTML via Flask Render
doc.add_root(plot)
bkapp = Application(FunctionHandler(modify_doc))
# This is so that if this app is run using something like "gunicorn -w 4" then
# each process will listen on its own port
sockets, port = bind_sockets("x.x.x.x", 0)
@app.route('/', methods=['GET'])
def bkapp_page():
script = server_document('http://x.x.x.x:%d/bkapp' % port)
return render_template("index.html", script=script, template="Flask")
def bk_worker():
asyncio.set_event_loop(asyncio.new_event_loop())
bokeh_tornado = BokehTornado({'/bkapp': bkapp}, extra_websocket_origins=["x.x.x.x:5000"])
bokeh_http = HTTPServer(bokeh_tornado)
bokeh_http.add_sockets(sockets)
server = BaseServer(IOLoop.current(), bokeh_tornado, bokeh_http)
server.start()
server.io_loop.start()
from threading import Thread
Thread(target=bk_worker).start()
Looking forward to any help!
P.S. intentionally replace the domain with x.x.x.x.
Solution
You didn’t include all the code, so you can’t be sure, but the most likely explanation is that you’re creating Bokeh models somewhere and reusing them between different calls to modify_doc
. This can occur, for example, if your create_figure
function references a global ColumnDataSource
(or other) that is created globally as a module outside the function. This doesn’t work, and Bokeh models can’t be reused across different documents/sessions. Each call to modify_doc needs to
return a whole new set of Bokeh models for session, otherwise different users will share state, which is not good for a number of reasons (so it is explicitly forbidden by throwing that exception).