散景-更新数据库更新图表

时间:2019-03-30 09:16:14

标签: python bokeh

编辑:我通过在更新函数中使用ColumnDataSource.data修复了TypeError,现在的问题是这是否是解决问题的正确方法。

我想显示一个仪表板,其中包含来自数据库的信息,我是Bokeh的新手,但我知道我需要运行Bokeh服务器应用程序。我的想法是在一个单独的线程中更新ColumnDataSource,但我不确定它是否可以工作。
这是我一直在尝试的测试,以查看是否可以更新情节,但得到TypeError: 'ColumnDataSource' object is not iterable

from bokeh.models.sources import ColumnDataSource
from bokeh.plotting import figure, curdoc
import time
from threading import Thread
from random import randint
from tornado import gen

from functools import partial

data = {'x': [1,2,3,4], 'y': [10, 20, 30, 40]}

source = ColumnDataSource(data)
p = figure(plot_width = 700, plot_height = 700, 
            title = 'Histogram of Arrival Delays by Carrier',
            x_axis_label = 'Delay (min)', y_axis_label = 'Proportion')

doc = curdoc()

@gen.coroutine
def update(x, y):
    source.data.update(ColumnDataSource({'x': x, 'y':y}).data)

def blocking_task():
    while True:
        # do some blocking computation
        time.sleep(5)
        x = [ randint(0,10) for _ in range(4)]
        y = [ randint(20, 80) for _ in range(4)]
        # but update the document from callback
        doc.add_next_tick_callback(partial(update, x=x, y=y))

p.hbar(y='x', height=0.2, right='y', source=source)
doc.add_root(p)
thread = Thread(target=blocking_task)
thread.start()

我不确定这是否是正确的方法,因此我们将不胜感激。

1 个答案:

答案 0 :(得分:1)

是的,只要您需要进行线程化,这就是正确的方法。一个小小的更正:不必在每次更新时都创建一个新的ColumnDataSource。您可以仅将新数据字典分配给现有的source.data。请参见下面的稍作修改的代码(适用于Bokeh v1.0.4)。

from bokeh.models.sources import ColumnDataSource
from bokeh.plotting import figure, curdoc
from functools import partial
from threading import Thread
from random import randint
from tornado import gen
import time

data = {'x': [1, 2, 3, 4], 'y': [10, 20, 30, 40]}
source = ColumnDataSource(data)
p = figure(plot_width = 700, plot_height = 700,
            title = 'Histogram of Arrival Delays by Carrier',
            x_axis_label = 'Delay (min)', y_axis_label = 'Proportion')

doc = curdoc()

@gen.coroutine
def update(x, y):
    source.data = {'x': x, 'y': y}

def blocking_task():
    while True:
        # do some blocking computation
        time.sleep(5)
        x = [ randint(0, 10) for _ in range(4)]
        y = [ randint(20, 80) for _ in range(4)]
        # but update the document from callback
        doc.add_next_tick_callback(partial(update, x = x, y = y))

p.hbar(y = 'x', height = 0.2, right = 'y', source = source)
doc.add_root(p)
thread = Thread(target = blocking_task)
thread.start()

如果不需要线程,则基于定期回调的方法更容易使用:

from bokeh.models.sources import ColumnDataSource
from bokeh.plotting import figure, curdoc
from random import randint
import time

data = {'x': [1, 2, 3, 4], 'y': [10, 20, 30, 40]}
source = ColumnDataSource(data)
p = figure(plot_width = 700, plot_height = 700,
            title = 'Histogram of Arrival Delays by Carrier',
            x_axis_label = 'Delay (min)', y_axis_label = 'Proportion')
p.hbar(y = 'x', height = 0.2, right = 'y', source = source)

def update():
    x = [ randint(0, 10) for _ in range(4)]
    y = [ randint(20, 80) for _ in range(4)]
    source.data = {'x': x, 'y': y}

curdoc().add_periodic_callback(update, 5000)
curdoc().add_root(p)

您使用以下代码运行代码:

bokeh serve --show app.py

结果:

enter image description here