flask сервер боке - рисунок не отображается даже локально - PullRequest
0 голосов
/ 08 января 2020

Я не могу запустить сервер Bokeh в flask beind apache, поэтому сейчас я пытаюсь обслуживать Bokeh в flask локально. Фигура не оказывает. Вот код flask:

from flask import Flask, render_template
app = Flask(__name__)

from bokeh.embed import server_document
@app.route("/")
def techblog():
    try:
        tag = server_document(url=r'/bokeh', relative_urls=True)
        return render_template('techblog.html', tag=tag)
    except Exception as e:
        return str(e)

if __name__ == '__main__':
    app.run(debug=True)

Код боке:

from numpy.random import random
from bokeh.io import curdoc
from bokeh.plotting import figure
from bokeh.layouts import column, widgetbox
from bokeh.models import Button, ColumnDataSource
from bokeh.server.server import Server

def run(doc):

    fig = figure(title='random data', width=400, height=200, tools='pan,box_zoom,reset,save')

    source = ColumnDataSource(data={'x': [], 'y': []})
    fig.line('x', 'y', source=source)

    def click(n=100):
        source.data = {'x': range(n), 'y': random(n)}

    button = Button(label='update', button_type='success')
    button.on_click(click)

    layout = column(widgetbox(button), fig)
    doc.add_root(layout)
    click()

# configure and run bokeh server
kws = {'port': 5000, 'prefix':'/bokeh','allow_websocket_origin': ['127.0.0.1']}
server = Server(run, **kws)
server.start()
# if __name__ == '__main__':
server.io_loop.add_callback(server.show, '/')
server.io_loop.start()

Вот мой шаблон html:

<h1 style='color:blue'>Hello There!</h1>

</br>
{{ tag|safe }}
</br>
{{ tag }}

I Я запускаю flask приложение через python. И на отдельном командном процессоре я запускаю приложение bokeh через

bokeh serve --allow-websocket-origin=localhost:5000 filename.py

Я получаю тег без «safe» только как

<script src="/bokeh/autoload.js?bokeh-autoload-element=1001&bokeh-app-path=/bokeh" id="1001"></script>

И у меня это сообщение на консоли flask , Это стандарт 404:

"GET /bokeh/autoload.js?bokeh-autoload-element=1000&bokeh-app-path=/bokeh HTTP/1.1" 404 -

Вот и все. Ни одна фигура или кнопка не отображаются. Что я должен изменить, чтобы увидеть рисунок?

Редактировать: я указал порт и префикс в коде боке. Результат не изменился.

Редактировать 2: Я добавил консоль msj для ошибки 404 на flask консоли.

Ответы [ 2 ]

2 голосов
/ 08 января 2020

Есть несколько неправильных вещей:

  • Вы не настроили порт, поэтому сервер Bokeh будет использовать порт по умолчанию 5006 (не 5000)

  • Вы не настроили путь к приложению, поэтому сервер Bokeh будет обслуживать приложение из местоположения по умолчанию / (не /bokeh)

Это также Стоит отметить, что если вы включили белый список localhost в качестве источника разрешения веб-сокета, то он буквально должен быть localhost в строке URL (т.е. не 127.0.0.1, они не являются взаимозаменяемыми в этом контексте)

Наконец, это большая дополнительная работа, чтобы поместить код приложения Bokeh в простой python скрипт, который вызывает Server вручную и т. д. c. Вы можете просто поместить содержимое run в файл и вызвать bokeh serve --port=5000 app.py, и тогда приложение будет доступно по localhost:5000/app

1 голос
/ 08 января 2020

Я добавляю некоторые подробности в ответ @ bigreddot.


Код тоже не работает для меня. Я даже нашел именно этот код в каком-то учебном пособии, и основная проблема заключалась в том, что он использовал nginx, который преобразовывал /bokeh в http://127.0.0.1/bokeh. Но на локальном компьютере без nginx я должен изменить все URL.

РЕДАКТИРОВАТЬ: Я нашел учебник с этим кодом https://rbtechblog.com/blog/deploy_bokeh_app


Я начинаю изменять код и сокращать его, чтобы создать минимальный код, который работает. Я внес изменения, аналогичные изменениям, упомянутым bigreddot.


Bokeh

Я поместил код непосредственно в файл без def и без Server

filename.py

from numpy.random import random
from bokeh.io import curdoc
from bokeh.plotting import figure
from bokeh.layouts import column, widgetbox
from bokeh.models import Button, ColumnDataSource

def click(n=100):
    source.data = {'x': range(n), 'y': random(n)}

fig = figure(title='random data', width=800, height=400, tools='pan,box_zoom,reset,save')

source = ColumnDataSource(data={'x': [], 'y': []}) # place for data
fig.line('x', 'y', source=source)  # draw plot

button = Button(label='update', button_type='success') # create button
button.on_click(click) # assign function to button

layout = column(fig, widgetbox(button)) # create layout
curdoc().add_root(layout) # add all to document

click() # generate random data at start

Теперь я могу запустить его в консоли

 bokeh serve filename.py 

, и я могу видеть его в веб-браузере, используя url

 http://localhost:5006/filename

(bokeh должен отображать этот URL в консоли после запуска - если вы будете использовать другой файл или опции, вы можете увидеть другой URL)

В данный момент мне не нужны никакие другие опции, но позже мне понадобятся --allow-websocket-origin, но я опишу это позже.

Кстати: Я не использую имя bokeh.py , потому что это может создать проблемы при импорте оригинала bokeh.


Flask

Поскольку я не использую nginx, который может конвертировать /bokeh в http://localhost:5006/filename, поэтому я должен использовать полный URL в serve_document

Для теста я использовал render_template_string вместо render_template, поэтому мне не нужно создавать templates/index.html, чтобы было проще копировать и тестировать код.

Я удалил try/except, чтобы получить больше Detai ls, если будет ошибка.

app.py

from flask import Flask, render_template, render_template_string
from bokeh.embed import server_document

app = Flask(__name__)

@app.route("/")
def index():
    tag = server_document(url='http://localhost:5006/filename')
    #return render_template('index.html', tag=tag)
    return render_template_string('''<div>{{ tag|safe }}</div>''', tag=tag)

if __name__ == '__main__':
    app.run(debug=True)

Теперь я могу запустить его

python app.py

и открыть страницу в веб-браузере, используя стандартный URL-адрес

http://localhost:5000/

, но я не вижу графика, и bokeh отобразит

Refusing websocket connection from Origin 'http://127.0.0.1:5000'; 
use --allow-websocket-origin=127.0.0.1:5000 
or set BOKEH_ALLOW_WS_ORIGIN=127.0.0.1:5000 to permit this; 
currently we allow origins {'localhost:5006'}

, поэтому мне нужно перезапустить bokeh с этой опцией

bokeh serve filename.py --allow-websocket-origin=127.0.0.1:5000

(как упомянул bigreddot, оно должно быть 127.0.0.1, а не localhost)

И теперь flask должен отображать график.

Кстати: если я использую шаблон без тега HTML

render_template_string('''{{ tag|safe }}''', tag=tag) 

, то браузер может обрабатывать весь код (<script ...></scrip>) как часть <head></head> и не будет отображать его, потому что браузер никогда не отображает элементы, которые находятся в <head></head>, даже если есть правильные изображения или графики.


...