python - 本地主机上的 Bokeh Web 服务器应用程序到 html 文件

标签 python python-3.x pandas bokeh

我一直在使用 Bokeh 网络服务器

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

我已经完成了脚本,一切都很顺利。我可以使用以下命令查看结果:bokehserve --show main.py

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

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 分支。

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

我尝试使用 bokeh.plotting 中的 show,但它显示本地主机路径作为命令 bokehserve --show main.py做过。

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

如有任何建议,我们将不胜感激!提前致谢。

更新

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

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)

最佳答案

如果您的应用程序在任何事件回调中调用实际的 python 库(例如上面显示的 numpypandas)(事实上,如果它甚至有任何 on_change 回调 ),那么就不可能制作一个“独立的 HTML 文件”(即可以简单地单独上传)来重现其功能。具体来说:浏览器无法执行python代码,没有numpypandas 。 Bokeh 服务器的主要目的是成为 Python 代码可以运行的地方,以响应 UI 事件。您需要在某处找到一些实际的服务器来运行和托管 Bokeh 服务器。

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

关于python - 本地主机上的 Bokeh Web 服务器应用程序到 html 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39111369/

相关文章:

Python Flask-Restful 错误 : Delete method in API is deleting ALL database entries

python - 如何使用 Pyinstaller 在 Windows 上制作 Mac 文件?

python - Pandas 过滤数据框的正值和负值

python pandas 从项集到数据框

python - 将 Django UserCreationForm 的密码验证错误从密码 2 移至密码 1

python 将数组拆分为运行/序列 - 最好是 numpy

安装 Spacy 模块后 Python 版本从 3.x 更改为 2.7

python - Pygame Text : Instead of colour, 让文字显示图片,或动画

python - 在 pandas 数据框中组合 groupby 后创建共享变量

python - 将数据帧拆分为多个 5 秒数据帧并在 Python 中获取计数