Bokeh web server app at localhost to html file

有些话、适合烂在心里 提交于 2019-12-11 13:15:48

问题


I have been working with bokeh web server.

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

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

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

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

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

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.

UPDATE

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)

回答1:


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.

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.



来源:https://stackoverflow.com/questions/39111369/bokeh-web-server-app-at-localhost-to-html-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!