这似乎不是Bokeh本身的问题,而是运行Flask应用程序的服务器中的线程和阻塞问题。
除了Bokeh,它完全可以重现…
import requestsfrom flask import Flask, jsonify, requestimport pandasimport pdbflask_app = Flask(__name__)# Populate some model maintained by the flask applicationmodelDf = pandas.Dataframe()nData = 100modelDf[ 'c1_x' ] = range(nData)modelDf[ 'c1_y' ] = [ x*x for x in range(nData) ]modelDf[ 'c2_x' ] = range(nData)modelDf[ 'c2_y' ] = [ 2*x for x in range(nData) ]@flask_app.route('/', methods=['GET'] )def index(): res = "<table>" res += "<tr><td><a href="http://localhost:8080/sendModelData/c1">SEND C1</a></td></tr>" res += "<tr><td><a href="http://localhost:8080/sendModelData/c2">SEND C2</a></td></tr>" res += "<tr><td><a href="http://localhost:8080/RequestsOverFlaskNoProxy?colName=c1">REQUEST OVER FLASK NO PROXY C1</a></td></tr>" res += "<tr><td><a href="http://localhost:8080/RequestsOverFlaskNoProxy?colName=c2">REQUEST OVER FLASK NO PROXY C2</a></td></tr>" res += "<tr><td><a href="http://localhost:8080/RequestsOverFlask?colName=c1">REQUEST OVER FLASK C1</a></td></tr>" res += "<tr><td><a href="http://localhost:8080/RequestsOverFlask?colName=c2">REQUEST OVER FLASK C2</a></td></tr>" res += "</table>" return res@flask_app.route('/RequestsOverFlaskNoProxy')def requestsOverFlaskNoProxy() : print("RequestsOverFlaskNoProxy") # get column name from query string colName = request.args.get('colName') # get model data from Flask url = "http://localhost:8080/sendModelData/%s" % colName print("Get data from %s" % url ) session = requests.Session() session.trust_env = False res = session.get( url , timeout=5000 , verify=False ) print( "CODE %s" % res.status_pre ) print( "ENCODING %s" % res.encoding ) print( "TEXT %s" % res.text ) data = res.json() return data@flask_app.route('/RequestsOverFlask')def requestsOverFlask() : # get column name from query string colName = request.args.get('colName') # get model data from Flask url = "http://localhost:8080/sendModelData/%s" % colName res = requests.get( url , timeout=None , verify=False ) print( "CODE %s" % res.status_pre ) print( "ENCODING %s" % res.encoding ) print( "TEXT %s" % res.text ) data = res.json() return data@flask_app.route('/sendModelData/<colName>' , methods=['GET'] )def sendModelData( colName ) : x = modelDf[ colName + "_x" ].tolist() y = modelDf[ colName + "_y" ].tolist() return jsonify( x=x , y=y )if __name__ == '__main__': print('Opening Flask app on http://localhost:8080/') # THIS DOES NOT WORK #flask_app.run( host='0.0.0.0' , port=8080 , debug=True ) # THIS WORKS flask_app.run( host='0.0.0.0' , port=8080 , debug=True , threaded=True )从屏幕截图中可以看出,直接从
sendModelDataJSon提供数据会适当地呈现JSon,但是通过
requests.getPython控制台中报告的503代码,通过该方法获取时会产生异常。
如果我尝试尝试消除通过环境变量启用的代理的影响,但这种方法将永远无法完成,并且请求将使浏览器无限期旋转。
想到它,甚至完全没有必要以中间人的身份使用请求,而且我应该能够只获取json字符串并自行反序列化。好吧,在我的实际代码中,通过在与Flask应用程序完全不同的python模块中完成Bokeh渲染,可以在此设置中起作用,因此除非我加扰应用程序的分层,否则这些功能甚至不可用。
编辑事实证明,我违反的基本原则是Flask的开发环境…
您正在通过Flask测试服务器运行WSGI应用程序,该服务器默认情况下使用单个线程来处理请求。因此,当您的一个请求线程尝试回拨到同一服务器时,它仍在忙于处理该请求。
https://stackoverflow.com/a/22878916/1330381
因此,问题就变成了如何在原始Bokeh示例中应用threaded = True技术?flask_embed.py示例对Tornado
WSGI服务器的依赖可能无法实现,从这个问题可以看出Tornado在设计上是单线程的。鉴于上述发现,一个甚至更尖锐的问题是,如何
AjaxDataSource共同避免
requests模块所面临的这些线程问题?
更新 有关散景和龙卷风耦合的更多背景信息…
53:05因此实际上它们不是很多,问题是关于Bokeh和Bokeh服务器的依赖关系。新的Bokeh服务器基于龙卷风构建,这几乎是主要依赖项,因为它使用了龙卷风。除此之外,对于Bokeh而言,没有太多依赖关系(运行时依赖关系)。pandas是Bokeh.charts的可选依赖项。还有其他依赖项,您知道使用了numpy。但是,我认为只有六个或七个依赖项。多年来,我们一直在努力将其削减很多,但是服务器的主要依赖性是龙卷风。Bokeh数据可视化简介-第1部分-
Strata Hadoop San Jose 2016



