本地的Bokeh Web服务器应用程序转换为html文件 [英] Bokeh web server app at localhost to html file

查看:92
本文介绍了本地的Bokeh Web服务器应用程序转换为html文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在和bokeh web server一起工作.

我使用自己的数据并按照以下示例创建了一个Web应用程序: https://github.com/bokeh/bokeh/blob/master/examples/app/movies/main.py

I created a web app, using my own data and following this example: https://github.com/bokeh/bokeh/blob/master/examples/app/movies/main.py

我已经完成了脚本,一切正常.我可以使用以下命令查看结果:bokeh serve --show main.py

I already finished the script and everything went ok. I can see the result using this command: bokeh serve --show main.py

我用来创建Web应用程序的模块是:

The modules I used to create the web app were:

from os.path import dirname, join
from pandas import Series, DataFrame
from bokeh.plotting import figure
from bokeh.layouts import layout, widgetbox
from bokeh.models import ColumnDataSource, HoverTool, Div
from bokeh.models.widgets import Slider, Select, TextInput
from bokeh.io import curdoc
from scipy import stats
import numpy as np
import pandas

但是,我的目标是将结果上传到我在github上的gh-pages分支中.

However, my goal is to upload the result to my gh-pages branch on github.

如何将bokeh中的结果另存为html文件以便在网页中使用?

How can I save the result from bokeh as html file in order to use it in a web page?

我尝试使用bokeh.plotting中的show,但是它显示了bokeh serve --show main.py命令所做的localhost路径.

I tried using show from bokeh.plotting, but it shows the localhost path as the command bokeh serve --show main.py did.

还有其他我可以使用的命令吗?

Is there an other command I could use?

任何建议,我们感激不尽!预先感谢.

Any suggestions are appreciated! Thanks in advance.

我使用此代码来获取解决方案.有了这段代码,我得到了一个html文件作为输出,但是需要改进.

I use this code to get a solution. With this code I got a html file as output, but it needs to be improved.

from os.path import dirname, join
from pandas import Series, DataFrame
from bokeh.plotting import figure
from bokeh.layouts import layout, widgetbox
from bokeh.models import ColumnDataSource, HoverTool, Div
from bokeh.models.widgets import Slider, Select, TextInput
from bokeh.io import curdoc
from bokeh.resources import JSResources
from bokeh.embed import file_html
from bokeh.util.browser import view
from jinja2 import Template
from scipy import stats
import numpy as np
import pandas

csvdata = pandas.read_csv('Alimentacion.csv', low_memory = False, encoding = 'latin-1')

# Convert amount field into int()
def str_to_int(mainList):
    for item in mainList:
        newList = [(int(item.replace('$', '').replace(',', '')) / (1000000)) for item in mainList]
    return newList

# Call str_to_int function
csvdata['CuantiaInt'] = str_to_int(csvdata['Cuantía'])
mean = np.mean(csvdata['CuantiaInt'])

# Assing colors to each contract by mean
csvdata['color'] = np.where(csvdata['CuantiaInt'] > mean, 'red', 'blue')
csvdata['alpha'] = np.where(csvdata['CuantiaInt'] > mean, 0.75, 0.75)

# Replace missing values (NaN) with 0
csvdata.fillna(0, inplace=True)

csvdata['revenue'] = csvdata.CuantiaInt.apply(lambda x: '{:,d}'.format(int(x)))

estados1 = [line.rstrip() for line in open('Estados1.txt')]
estados2 = [line.rstrip() for line in open('Estados2.txt')]

csvdata.loc[csvdata.Estado.isin(estados1), 'color'] = 'grey'
csvdata.loc[csvdata.Estado.isin(estados1), 'alpha'] = 0.75

csvdata.loc[csvdata.Estado.isin(estados2), 'color'] = 'brown'
csvdata.loc[csvdata.Estado.isin(estados2), 'alpha'] = 0.75

csvdata['z score'] = stats.zscore(csvdata['CuantiaInt'])
csvdata['sigma'] = np.std(csvdata['CuantiaInt'])

date_time = pandas.DatetimeIndex(csvdata['Fecha (dd-mm-aaaa)'])
newdates = date_time.strftime('%Y')
newdates = [int(x) for x in newdates]
csvdata['dates'] = newdates
csvdata['Dptos'] = csvdata['Loc dpto']
csvdata['Entidad'] = csvdata['Entidad Compradora']
csvdata['Proceso'] = csvdata['Tipo de Proceso']

axis_map = {
    'Cuantía y promedio': 'z score',
    'Cuantía (Millones de pesos)': 'CuantiaInt',
    'Desviación estándar': 'sigma',
    'Fecha del contrato': 'dates',
}

desc = Div(text=open(join(dirname(__file__), 'alimentacion.html')).read(), width=800)

DptosList = [line.rstrip() for line in open('locdpto.txt')]
ProcesosList = [line.rstrip() for line in open('tipoproceso.txt')]
EntidadesList = [line.rstrip() for line in open('entidades.txt')]

# Create Input controls
min_year = Slider(title = 'Año inicial', start = 2012, end = 2015, value = 2013, step = 1)
max_year = Slider(title = 'Año final', start = 2012, end = 2015, value = 2014, step = 1)
boxoffice = Slider(title = 'Costo del contrato (Millones de pesos)', start = 0, end = 77000, value = 0, step = 2)
dptos = Select(title = 'Departamentos', value = 'Todos los departamentos', options = DptosList)
proceso = Select(title = 'Tipo de Proceso', value = 'Todos los procesos', options = ProcesosList)
entidades = Select(title = 'Entidad Compradora', value = 'Todas las entidades', options = EntidadesList)
objeto = TextInput(title='Objeto del contrato')
x_axis = Select(title = 'X Axis', options = sorted(axis_map.keys()), value = 'Fecha del contrato')
y_axis = Select(title = 'Y Axis', options = sorted(axis_map.keys()), value = 'Cuantía (Millones de pesos)')

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

hover = HoverTool(tooltips=[
    ("Entidad", "@entidad"),
    ("Año", "@year"),
    ("$", "@revenue" + ' Millones de pesos')
])

p = figure(plot_height=500, plot_width=700, title='', toolbar_location=None, tools=[hover])
p.circle(x = 'x', y = 'y', source = source, size = 7, color = 'color', line_color = None, fill_alpha = 'alpha')

def select_contracts():
    dptos_val = dptos.value
    proceso_val = proceso.value
    entidades_val = entidades.value
    objeto_val = objeto.value.strip()
    selected = csvdata[
        (csvdata.dates >= min_year.value) &
        (csvdata.dates <= max_year.value) &
        (csvdata.CuantiaInt >= boxoffice.value)
    ]
    if dptos_val != 'Todos los departamentos':
        selected = selected[selected.Dptos.str.contains(dptos_val) == True]
    if proceso_val != 'Todos los procesos':
        selected = selected[selected.Proceso.str.contains(proceso_val) == True]
    if entidades_val != 'Todas las entidades':
        selected = selected[selected.Entidad.str.contains(entidades_val) == True]
    if objeto_val != '':
        selected = selected[selected.Objeto.str.contains(objeto_val) == True]

    return selected

def update():
    df = select_contracts()
    x_name = axis_map[x_axis.value]
    y_name = axis_map[y_axis.value]

    p.xaxis.axis_label = x_axis.value
    p.yaxis.axis_label = y_axis.value
    p.title.text = '%d contratos seleccionados' % len(df)

    source.data = dict(
        x = df[x_name],
        y = df[y_name],
        color = df['color'],
        entidad = df['Entidad'],
        year = df['dates'],
        revenue = df["revenue"],
        alpha = df['alpha'],
    )

controls = [min_year, max_year, boxoffice, dptos, proceso, entidades, objeto, x_axis, y_axis]

for control in controls:
    control.on_change('value', lambda attr, old, new: update())

sizing_mode = 'fixed'

inputs = widgetbox(*controls, sizing_mode=sizing_mode)

l = layout([
        [desc],
        [inputs, p],
    ], sizing_mode=sizing_mode)

update()

curdoc().add_root(l)
curdoc().title = "Contratos"

with open('../Contratos/Alimentación/alimentacion.jinja', 'r') as f:
    template = Template(f.read())

js_resources = JSResources(mode='inline')
html = file_html(l, resources=(js_resources, None), title="Contracts", template=template)
output_file = '../test.html'

with open(output_file, 'w') as f:
    f.write(html)

view(output_file)

推荐答案

如果您的应用在其任何事件回调(实际上,如果它甚至根本没有任何on_change回调 ),那么就不可能制作一个能够重现其功能的独立HTML文件"(即可以简单地单独上传).具体来说:浏览器无法执行python代码,没有numpypandas. Bokeh服务器的主要用途是 python代码可以运行的地方,以响应UI事件.您将需要在某处找到一些实际的服务器来运行和托管Bokeh服务器.

If your app makes calls to actual python libraries (e.g. numpy and pandas that you show above) in any of its event callbacks (in fact, if it even has any on_change callbacks at all), then it is not possible to make a "standalone HTML file" (i.e. that can be simply uploaded in isolation) that will reproduce its functionality. Specifically: browsers cannot execute python code, do not have numpy and pandas. The main purpose of the Bokeh server is to be the place where python code can run, in response to UI events. You will need to find some actual server somewhere to run and host a Bokeh server.

如果您将Bokeh服务器永久托管在某个地方,并且询问如何将运行在其上的Bokeh应用程序嵌入到gh-pages上的静态页面中,那么答案是使用autoload_server或将服务器应用程序URL嵌入到<iframe>可以很好地工作.

If you have the Bokeh server hosted somewhere permanently, and are asking how to embed a Bokeh app running on it into a static page on gh-pages then the answer is to use autoload_server or alternatively embedding the server app URL with an <iframe> works perfectly well.

这篇关于本地的Bokeh Web服务器应用程序转换为html文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆