我最近建立了一个包含bokeh小部件的仪表板。每次运行它时,我都需要转到anaconda提示符并键入
散景服务-显示myapp.py
是否有一种更友好的方式来执行此操作而无需打开cmd窗口?我目前在Windows 7上,很快就会更新到Windows 10。
谢谢!
答案 0 :(得分:0)
在Bokeh文档中对此进行了解释:Running a Bokeh Server
这是Bokeh v1.1.0的一个示例:
from tornado.ioloop import IOLoop
from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource
import random
def make_document(doc):
source = ColumnDataSource({'x': [], 'y': [], 'color': []})
def update():
new = {'x': [random.random()], 'y': [random.random()], 'color': [random.choice(['red', 'blue', 'green'])]}
source.stream(new)
doc.add_periodic_callback(update, 1000)
fig = figure(title = 'Streaming Circle Plot!', x_range = [0, 1], y_range = [0, 1])
fig.circle(source = source, x = 'x', y = 'y', color = 'color', size = 10)
doc.title = "Now with live updating!"
doc.add_root(fig)
apps = {'/': Application(FunctionHandler(make_document))}
io_loop = IOLoop.current()
server = Server(applications = {'/': Application(FunctionHandler(make_document))}, io_loop = io_loop, port = 5001)
server.start()
server.show('/')
io_loop.start()
答案 1 :(得分:0)
这是从Bokey电影示例(Bokeh v1.1.0)转换而来的请求代码:
from tornado.ioloop import IOLoop
from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from os.path import dirname, join
import numpy as np
import pandas.io.sql as psql
import sqlite3 as sql
from bokeh.plotting import figure
from bokeh.layouts import layout, column
from bokeh.models import ColumnDataSource, Div
from bokeh.models.widgets import Slider, Select, TextInput
from bokeh.io import curdoc
from bokeh.sampledata.movies_data import movie_path
def make_document(doc):
conn = sql.connect(movie_path)
query = open(join(dirname(__file__), 'query.sql')).read()
movies = psql.read_sql(query, conn)
movies["color"] = np.where(movies["Oscars"] > 0, "orange", "grey")
movies["alpha"] = np.where(movies["Oscars"] > 0, 0.9, 0.25)
movies.fillna(0, inplace = True) # just replace missing values with zero
movies["revenue"] = movies.BoxOffice.apply(lambda x: '{:,d}'.format(int(x)))
with open(join(dirname(__file__), "razzies-clean.csv")) as f:
razzies = f.read().splitlines()
movies.loc[movies.imdbID.isin(razzies), "color"] = "purple"
movies.loc[movies.imdbID.isin(razzies), "alpha"] = 0.9
axis_map = {
"Tomato Meter": "Meter",
"Numeric Rating": "numericRating",
"Number of Reviews": "Reviews",
"Box Office (dollars)": "BoxOffice",
"Length (minutes)": "Runtime",
"Year": "Year",
}
desc = Div(text = open(join(dirname(__file__), "description.html")).read(), width = 800)
# Create Input controls
reviews = Slider(title = "Minimum number of reviews", value = 80, start = 10, end = 300, step = 10)
min_year = Slider(title = "Year released", start = 1940, end = 2014, value = 1970, step = 1)
max_year = Slider(title = "End Year released", start = 1940, end = 2014, value = 2014, step = 1)
oscars = Slider(title = "Minimum number of Oscar wins", start = 0, end = 4, value = 0, step = 1)
boxoffice = Slider(title = "Dollars at Box Office (millions)", start = 0, end = 800, value = 0, step = 1)
genre = Select(title = "Genre", value = "All",
options = open(join(dirname(__file__), 'genres.txt')).read().split())
director = TextInput(title = "Director name contains")
cast = TextInput(title = "Cast names contains")
x_axis = Select(title = "X Axis", options = sorted(axis_map.keys()), value = "Tomato Meter")
y_axis = Select(title = "Y Axis", options = sorted(axis_map.keys()), value = "Number of Reviews")
# Create Column Data Source that will be used by the plot
source = ColumnDataSource(data = dict(x = [], y = [], color = [], title = [], year = [], revenue = [], alpha = []))
TOOLTIPS = [
("Title", "@title"),
("Year", "@year"),
("$", "@revenue")
]
p = figure(plot_height = 600, plot_width = 700, title = "", toolbar_location = None, tooltips = TOOLTIPS)
p.circle(x = "x", y = "y", source = source, size = 7, color = "color", line_color = None, fill_alpha = "alpha")
def select_movies():
genre_val = genre.value
director_val = director.value.strip()
cast_val = cast.value.strip()
selected = movies[
(movies.Reviews >= reviews.value) &
(movies.BoxOffice >= (boxoffice.value * 1e6)) &
(movies.Year >= min_year.value) &
(movies.Year <= max_year.value) &
(movies.Oscars >= oscars.value)
]
if (genre_val != "All"):
selected = selected[selected.Genre.str.contains(genre_val) == True]
if (director_val != ""):
selected = selected[selected.Director.str.contains(director_val) == True]
if (cast_val != ""):
selected = selected[selected.Cast.str.contains(cast_val) == True]
return selected
def update():
df = select_movies()
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 movies selected" % len(df)
source.data = dict(
x = df[x_name],
y = df[y_name],
color = df["color"],
title = df["Title"],
year = df["Year"],
revenue = df["revenue"],
alpha = df["alpha"],
)
controls = [reviews, boxoffice, genre, min_year, max_year, oscars, director, cast, x_axis, y_axis]
for control in controls:
control.on_change('value', lambda attr, old, new: update())
inputs = column(*controls)
l = layout([
[desc],
[inputs, p],
])
update() # initial load of the data
doc.add_root(l)
doc.title = "Movies"
io_loop = IOLoop.current()
server = Server(applications = {'/': Application(FunctionHandler(make_document))}, io_loop = io_loop, port = 5001)
server.start()
server.show('/')
io_loop.start()