将文件信息从html文件选择器输入传递给python和bokeh

时间:2016-08-29 12:30:09

标签: python html bokeh

我正在尝试创建一个简单的散景服务器应用程序,允许用户从<input type="file">文件选择按钮加载文件。然后,应用程序将绘制用户选择的文件中的数据。下面的代码非常简单,我根本不知道如何将文件信息从文件选择器传递给python。我需要使用python来处理文件I / O而不是html或javascript。

当我在命令行运行bokeh serve --show example.py path/to/input_file时,我可以正常工作,但我不希望用户每次都指定它。我需要它们能够单击按钮来“上传”文件。此应用程序在本地运行,因此无法上传到服务器或类似的任何内容。

有比<input type="file">更好的方法吗?

from bokeh.plotting import figure
from bokeh.layouts import layout
from bokeh.models import ColumnDataSource, Div
from bokeh.io import curdoc

desc = Div(text="""
<h1>A simple example</h1>
<input type="file">
<br />""", width=800)

# Create Column Data Source that will be used by the plot
source = ColumnDataSource(data=dict(x=[], y=[]))

p = figure(plot_height=550, plot_width=800, title="", toolbar_location='above')
p.line(x="x", y="y", source=source)

def update():
    x_data,y_data = read_file_data(input_file_name) # function to read specific file type
    source.data = dict(
        x=x_data,
        y=y_data,
    )

sizing_mode = 'fixed'  # 'scale_width' also looks nice with this example
l = layout([
    [desc],
    [p],
], sizing_mode=sizing_mode)

update()
curdoc().add_root(l)
curdoc().title = "Sample"

2 个答案:

答案 0 :(得分:5)

截至Bokeh 0.12.4,没有内置文件选择器输入小部件。但是create new extensions to Bokeh可以像内置小部件一样无缝地将JS事件连接到Python。

下面的代码是一个模型的超粗略实现,它包装<input type="file">以将其连接到Python代码。此代码应与Bokeh 0.12.4及更新版本一起使用。

from bokeh.core.properties import String
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models import Button, LayoutDOM

IMPL = """
import * as p from "core/properties"
import {LayoutDOM, LayoutDOMView} from "models/layouts/layout_dom"

export class FileInputView extends LayoutDOMView
  initialize: (options) ->
    super(options)
    input = document.createElement("input")
    input.type = "file"
    input.onchange = () =>
      @model.value = input.value
    @el.appendChild(input)

export class FileInput extends LayoutDOM
  default_view: FileInputView
  type: "FileInput"
  @define {
    value: [ p.String ]
  }
"""

class FileInput(LayoutDOM):
    __implementation__ = IMPL
    value = String()

input = FileInput()

def upload():
    print(input.value)
button = Button(label="Upload")
button.on_click(upload)

curdoc().add_root(column(input, button))

这导致以下输出:

enter image description here

几乎可以肯定会对此做出改进。对于迭代和协作讨论来说,SO并不是一个好地方,所以如果你对改进这个问题有疑问,我建议将public mailing list作为继续进行的最佳选择。

答案 1 :(得分:0)

我面临同样的任务(将文件传递给Bokeh小部件),但还有一些其他限制(Tornado带有嵌入式Bokeh服务器)。所以下面的代码不是确切的解决方案,但它可以帮助:

Tornado HTTP网页,带有嵌入式Bokeh小部件,可与同一应用程序的其他页面进行通信 https://gist.github.com/Sklavit/c378a18661f0d91918931eba5a1d7553