Python: запустить сервер Bokeh при обработке ввода данных виджетов - PullRequest
0 голосов
/ 30 августа 2018

У меня есть крошечный проект, который становится все больше и больше. Поэтому я решил разделить проект на отдельные модули. Теперь у меня проблема с управлением обработчиком событий .on_change виджетов bokeh.

Каталог приложения bokeh выглядит так:

bokeh_app_test
   |
   +---scripts
   |    +---__init__.py
   |    +---corporates .py
   |
   +---__init__.py
   +---main.py

Я запускаю приложение через Windows cmd: python -m bokeh serve --show bokeh_app_test

Сервер Python 3.6.6 Anaconda и Bokeh версия 0.13.0

main.py:

import datetime
from bokeh.io import curdoc
from bokeh.models.widgets import Tabs

# scripts
from scripts.corporates import Corporate

# =============================================================================
# definitions
# =============================================================================
StartDate = datetime.date(2018,1,1)
EndDate = datetime.date(2018,8,30)
lLevel1 = ['Corporates', 'Sovereigns', 'Collateralized']

# =============================================================================
# programm code
# =============================================================================
corptab = Corporate(lLevel1,StartDate,EndDate)
corporate_tab = corptab.corp_tab()
tabs = Tabs(tabs = [corporate_tab])
curdoc().add_root(tabs)

и corporates.py

from bokeh.layouts import gridplot
from bokeh.models.widgets import Panel, PreText, DatePicker, Select

class Corporate(object):

    def __init__(self, lLevel1, StartDate, EndDate):
        self.lLevel1 = lLevel1
        self.EndDate = EndDate
        self.StartDate = StartDate
        self.corp_date_picker1 = DatePicker(min_date=self.StartDate,
                          max_date= self.EndDate,
                          value=(self.StartDate),
                          title="Start")
        self.corp_date_picker2 = DatePicker(min_date= self.StartDate,
                          max_date= self.EndDate,
                          value=(self.EndDate),
                          title="End")
        self.corp_level_select = Select(title="Level1:",
                      value="Sovereigns",
                      options=self.lLevel1)
        self.text = PreText(text='', width=1000)

    def corp_date_picker1_change(attrname, old, new):
        self.update_corp_data()

    def corp_date_picker2_change(attrname, old, new):
        self.update_corp_data()

    def corp_level_select_change(attrname, old, new):
        self.update_corp_data()

    def update_corp_data(self):
        StartDate = self.corp_date_picker1.value
        EndDate = self.corp_date_picker2.value
        Level = self.corp_level_select.value

        self.text.text= "StartDate:{}; EndDate:{}; Level: {}".format(StartDate,EndDate,Level)

    def corp_tab(self):
        grid = gridplot([[self.corp_date_picker1, self.corp_date_picker2, self.corp_level_select],
                         [self.text]])
        self.corp_date_picker1.on_change('value', Corporate.corp_date_picker1_change)
        self.corp_date_picker2.on_change('value', Corporate.corp_date_picker2_change)
        self.corp_level_select.on_change('value', Corporate.corp_level_select_change)
        tab = Panel(child=grid, title='TAB 1')
        self.update_corp_data()
        return tab

ERROR

Сервер запускается без ошибок, и виджеты отображаются так, как предполагалось: введите описание изображения здесь

Однако, если я изменю значения виджетов, появится следующая ошибка:

2018-08-30 15:37:24,692 error handling message Message 'PATCH-DOC' (revision 1): NameError("name 'self' is not defined",)

спасибо Пол

1 Ответ

0 голосов
/ 31 августа 2018

Я нашел одно решение: Функция обратного вызова .on_change допускает только «attr, old, new», однако мне тоже нужно self. Поэтому я вырезал обратный вызов и вставил его в основную программу. У кого-нибудь есть лучшее решение?

main.py

import datetime
from bokeh.io import curdoc
from bokeh.models.widgets import Tabs

# scripts
from scripts.corporates import Corporate

# =============================================================================
# definitions
# =============================================================================
StartDate = datetime.date(2018,1,1)
EndDate = datetime.date(2018,8,30)
lLevel1 = ['Corporates', 'Sovereigns', 'Collateralized']

# =============================================================================
# programm code
# =============================================================================
corptab = Corporate(lLevel1,StartDate,EndDate)
corporate_tab = corptab.corp_tab()

def corptab_change(attrname, old, new):
        corptab.update_corp_data(corptab.corp_date_picker1.value,
                                 corptab.corp_date_picker2.value,
                                 corptab.corp_level_select.value)
corptab.corp_date_picker1.on_change('value', corptab_change)
corptab.corp_date_picker2.on_change('value', corptab_change)
corptab.corp_level_select.on_change('value', corptab_change)



tabs = Tabs(tabs = [corporate_tab])
curdoc().add_root(tabs)

corporates.py

from bokeh.layouts import gridplot
from bokeh.models.widgets import Panel, PreText, DatePicker, Select

class Corporate(object):

    def __init__(self, lLevel1, StartDate, EndDate):
        self.lLevel1 = lLevel1
        self.EndDate = EndDate
        self.StartDate = StartDate
        self.corp_date_picker1 = DatePicker(min_date=self.StartDate,
                          max_date= self.EndDate,
                          value=(self.StartDate),
                          title="Start")
        self.corp_date_picker2 = DatePicker(min_date= self.StartDate,
                          max_date= self.EndDate,
                          value=(self.EndDate),
                          title="End")
        self.corp_level_select = Select(title="Level1:",
                      value="Sovereigns",
                      options=self.lLevel1)
        self.text = PreText(text='', width=1000)

    def update_corp_data(self, StartDate, EndDate, Level):
        StartDate = StartDate
        EndDate = EndDate
        Level = Level

        self.text.text= "StartDate:{}; EndDate:{}; Level: {}".format(StartDate,EndDate,Level)

    def corp_tab(self):
        grid = gridplot([[self.corp_date_picker1, self.corp_date_picker2, self.corp_level_select],
                         [self.text]])
        tab = Panel(child=grid, title='TAB 1')
        self.update_corp_data(self.corp_date_picker1.value,
                              self.corp_date_picker2.value,
                              self.corp_level_select.value)
        return tab
...