Flask 烧瓶+;Bokeh AjaxDataSource

Flask 烧瓶+;Bokeh AjaxDataSource,flask,bokeh,Flask,Bokeh,与Flask+Bokeh AjaxDataSource的斗争: 我有一个返回json数据的函数: @app.route("/data", methods=['POST']) def get_x(): global x, y x = x + 0.1 y = math.sin(x) return flask.jsonify(x=[x], y=[y]) 我可以将其与Bokeh AjaxDataSource一起使用创建流式绘图没有问题: source = AjaxDat

与Flask+Bokeh AjaxDataSource的斗争:

我有一个返回json数据的函数:

@app.route("/data", methods=['POST'])
def get_x():
    global x, y
    x = x + 0.1
    y = math.sin(x)
    return flask.jsonify(x=[x], y=[y])
我可以将其与Bokeh AjaxDataSource一起使用创建流式绘图没有问题:

source = AjaxDataSource(data_url="http://localhost:5000/data", polling_interval=1000, mode='append')
p = figure()
p.line('x', 'y', source=source)                                                                       
show(p)
但是,当我尝试将其嵌入flask页面时,AjaxDataSource不会查询服务器。绘图无法渲染,没有错误。请注意,如果我使用静态绘图而不是AjaxDataSource,它可以很好地进行绘图。以下是相关代码:

template = Template('''<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Streaming Example</title>
        {{ js_resources }}
        {{ css_resources }}
    </head>
    <body>
    {{ plot_div }}
    {{ plot_script }}
    </body>
</html>
''')

@app.route("/")
def simple():
    streaming=True
    source = AjaxDataSource(data_url="http://localhost:5000/data", 
                            polling_interval=1000, mode='append')

    fig = figure(title="Streaming Example")
    fig.line( 'x', 'y', source=source)

    js_resources = INLINE.render_js()
    css_resources = INLINE.render_css()

    script, div = components(fig, INLINE)

    html = template.render(
        plot_script=script,
        plot_div=div,
        js_resources=js_resources,
        css_resources=css_resources
    )

    return encode_utf8(html) 
template=模板(“”)
流媒体示例
{{js_resources}}
{{css_resources}}
{{plot_div}}
{{plot_script}}
''')
@附件路线(“/”)
def simple():
流=真
source=AjaxDataSource(数据\u url=”http://localhost:5000/data", 
轮询(间隔=1000,模式='append')
图=图(title=“流媒体示例”)
图线('x','y',震源=震源)
js_resources=INLINE.render_js()
css\u resources=INLINE.render\u css()
脚本,div=组件(图,内联)
html=template.render(
绘图脚本=脚本,
plot_div=div,
js_resources=js_resources,
css\u资源=css\u资源
)
返回编码utf8(html)
如果有人有任何想法,我会很感激的


Brian

首先,作为一个温和的建议,请始终发布完整的可运行代码示例。复制所有丢失的必要导入只需几分钟,一旦有可运行的脚本,诊断只需几秒钟


更新:由于Bokeh
0.12.15
不需要下面描述的解决方法
AjaxDataSource
应该毫无怨言地流到一张空CD中,前面没有创建空列


最近,BokehJS的一些代码路径变得更加“严格”,这在几乎所有情况下都是好的,但这似乎留下了与
AjaxDataSource
的不良交互,这一点没有引起注意。FWIW运行示例时,我确实在浏览器JS控制台中看到一个错误:

Error: attempted to retrieve property array for nonexistent field 'x'
这是工作循环的关键,这只是为了确保数据源确实有
x
y
的(空)列:

source.data = dict(x=[], y=[])
下面有一个完整的工作脚本。我想请你用这些信息在上提出一个问题,这样这个bug就可以被优先排序和修复


从烧瓶导入烧瓶,jsonify
从jinja2导入模板
输入数学
从bokeh.plotting导入图形
从bokeh.models导入AjaxDataSource
从bokeh.embed导入组件
从bokeh.resources内联导入
从bokeh.util.string导入编码
app=烧瓶(名称)
x、 y=0,0
@app.route(“/data”,方法=['POST']))
def get_x():
全局x,y
x=x+0.1
y=数学sin(x)
返回jsonify(x=[x],y=[y])
模板=模板(“”)
流媒体示例
{{js_resources}}
{{css_resources}}
{{plot_div}}
{{plot_script}}
''')
@附件路线(“/”)
def simple():
流=真
source=AjaxDataSource(数据\u url=”http://localhost:5000/data",
轮询(间隔=1000,模式='append')
source.data=dict(x=[],y=[])
图=图(title=“流媒体示例”)
图线('x','y',震源=震源)
js_resources=INLINE.render_js()
css\u resources=INLINE.render\u css()
脚本,div=组件(图,内联)
html=template.render(
绘图脚本=脚本,
plot_div=div,
js_resources=js_resources,
css\u资源=css\u资源
)
返回编码utf8(html)
app.run(debug=True)

与OP一样,我也想将AJAX与Bokeh和Flask结合使用。但是,我不想用
AjaxDataSource
连续地从服务器上传输数据,我只想在用户与网页上的输入交互时从服务器上获取新数据。为了实现这一点,我使用bigreddot作为基础,将
AjaxDataSource
更改为
ColumnDataSource
,并在
CustomJS
中添加了一个jQuery AJAX调用(以下示例是使用Python 3.6.4、Flask 1.0.2和Bokeh 0.13.0创建的):

导入json
从烧瓶导入烧瓶,jsonify,请求
从jinja2导入模板
从bokeh.plotting导入图形
从bokeh.models导入ColumnDataSource、CustomJS中,选择
从bokeh.embed导入组件
从bokeh.resources内联导入
从bokeh.layouts导入列
从bokeh.util.string导入编码
app=烧瓶(名称)
N_数据点=20
默认_变量='bar'
MY_数据库={
‘foo’:[i**1表示范围内的i(N_数据点)],
'条形图':[i**2表示范围内的i(N_数据点)],
'baz':[i**3表示范围内的i(N_数据点)]]
@app.route(“/get\u new\u data”,方法=['POST']))
def get_new_data():
app.logger.info(
“浏览器通过AJAX发送了以下内容:%s”,json.dumps(request.form))
变量\u to\u return=请求。表单['please\u return\u data\u of \u this\u variable']
return jsonify({variable_to_return:MY_数据库[variable_to_return]})
简单HTML模板=模板(“”)
{{js_resources}}
{{css_resources}}
{{plot_div}}
{{plot_script}}
''')
@附件路线(“/”)
def simple():
x=范围(N_数据点)
y=我的_数据库[默认_变量]
source=ColumnDataSource(数据=dict(x=x,y=y))
plot=图(title=“Flask+JQuery-AJAX-in-Bokeh-CustomJS”)
绘图线('x','y',震源=震源,线宽=3,线α=0.6)
callback=CustomJS(args=dict(source=source),code=”“”
所选var_值=cb_对象值;
var plot_data=源数据;
jQuery.ajax({
键入:“POST”,
url:“/获取新数据”,
数据:{“请返回此变量的数据”:所选值},
数据类型:“json”,
成功:函数(json_来自_服务器){
//警报(JSON.stringify(JSON_来自_服务器));
plot_data.y=json_from_server[所选的_值];
source.change.emit();
},
呃
from flask import Flask, jsonify
from jinja2 import Template
import math

from bokeh.plotting import figure
from bokeh.models import AjaxDataSource
from bokeh.embed import components
from bokeh.resources import INLINE
from bokeh.util.string import encode_utf8


app = Flask(__name__)

x, y = 0, 0

@app.route("/data", methods=['POST'])
def get_x():
    global x, y
    x = x + 0.1
    y = math.sin(x)
    return jsonify(x=[x], y=[y])

template = Template('''<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Streaming Example</title>
        {{ js_resources }}
        {{ css_resources }}
    </head>
    <body>
    {{ plot_div }}
    {{ plot_script }}
    </body>
</html>
''')

@app.route("/")
def simple():
    streaming=True
    source = AjaxDataSource(data_url="http://localhost:5000/data",
                            polling_interval=1000, mode='append')

    source.data = dict(x=[], y=[])

    fig = figure(title="Streaming Example")
    fig.line( 'x', 'y', source=source)

    js_resources = INLINE.render_js()
    css_resources = INLINE.render_css()

    script, div = components(fig, INLINE)

    html = template.render(
        plot_script=script,
        plot_div=div,
        js_resources=js_resources,
        css_resources=css_resources
    )

    return encode_utf8(html)

app.run(debug=True)