Точка входа для сервера Bokeh

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

$ bokeh serve --show my_package/tools/my_tool.py

Который открывает браузер и показывает интерактивный сюжет. Однако, когда я устанавливаю этот пакет с помощью pip/ PyPI, пользователи не могут легко получить доступ к этой папке, поэтому я хотел бы указать точку входа для этого в моем файле setup.py.

Макет пакета:
folder
|
|--- my_package
|     |
|     |- __init__.py
|     |- __main__.py
|     |- some_code.py
|     |
|     +--- tools
|           |
|           +--- my_tool.py
|
+--setup.py

В моем setup.py я уже указываю точку входа в мой основной метод:

setup.py
from setuptools import setup, find_packages

setup(
    name = "my_package",
    packages = find_packages(),
    entry_points = {
        'console_scripts': [
            'my_package = my_package.__main__:main'
          ]
    },
    [...],
)

Тем не менее, я нашел единственный способ запустить сервер Bokeh и показать интерфейс - создать еще один скрипт на Python, подобный этому.

import os
from subprocess import call

def main():
    p = os.path.realpath(__file__)
    prefix, _ = os.path.split(p)
    bokeh_server_file = os.path.join(prefix, "my_tool.py")
    call(["bokeh", "serve", "--show", bokeh_server_file])

if __name__ == "__main__":
    main()

поместите это в tools папку и создать точку входа для этого метода сценариев основного. * дрожь * Должен быть лучший способ сделать это.

Можно ли предоставить такую ​​точку входа с помощью setuptools или есть другой способ добиться такого поведения?

2 ответа

Решение

Если я не ошибаюсь, вы можете пойти по маршруту встроенного сервера, который описан в Embedded Bokeh Server как документ библиотеки. Далее следуют указания по использованию API-интерфейса сервера bokeh, следуя этой части документации. Похоже, что они работают над новыми способами подключения к серверу в будущем, а также в той части, где обсуждаются варианты использования.

Чтобы расширить ответ @jxramos, я изменил пример автономного встраивания, приведенный на странице. Управляя циклом ввода-вывода tornado самостоятельно в главной функции, вы можете заставить свой скрипт bokeh вести себя как обычный скрипт на python, который автоматически запускает браузер при запуске.

from tornado.ioloop import IOLoop
from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
from bokeh.server.server import Server

def modify_doc(doc):
    """Function that modifies a document."""
    # [...] create a plot
    doc.add_root(plot)
    doc.title = "Test Plot"

def main():
    """Launch the server and connect to it."""
    io_loop = IOLoop.current()
    bokeh_app = Application(FunctionHandler(modify_doc)) # pass the function that assembles your document here.
    server = Server({"/": bokeh_app}, io_loop=io_loop)
    server.start()
    print("Opening Bokeh application on http://localhost:5006/")

    io_loop.add_callback(server.show, "/")
    io_loop.start()

main()

Этот скрипт может быть вызван из командной строки

$ python my_tool.py

и, следовательно, будет использоваться для точки входа, как и ожидалось:

[...]
entry_points = {
    'console_scripts': [
        'my_package = my_package.tools.my_tool:main'
      ]
},
[...]

Общая версия

Ниже приведен более полный пример, который я перенес из примера документации, который я написал. Поскольку документация постепенно сокращается, я думаю, что она лучше подходит как часть этого ответа.

Локальный сервер боке с консольной точкой входа

Чтобы приложение bokeh могло быть выполнено как обычный файл.py, вам нужно обработать IO loop торнадо в вашем приложении, как описано здесь. Такое автономное приложение bokeh можно использовать для реализации точки входа консольного скрипта в setup.py, Однако для этого требуется версия bokeh > = 0.12.4.

Приложение боке

Рассмотрим файл local_server.py:

from tornado.ioloop import IOLoop

from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.server.server import Server


def modify_doc(doc):
    """Add a plotted function to the document.

    Arguments:
        doc: A bokeh document to which elements can be added.
    """
    x_values = range(10)
    y_values = [x ** 2 for x in x_values]
    data_source = ColumnDataSource(data=dict(x=x_values, y=y_values))
    plot = figure(title="f(x) = x^2",
                  tools="crosshair,pan,reset,save,wheel_zoom",)
    plot.line('x', 'y', source=data_source, line_width=3, line_alpha=0.6)
    doc.add_root(plot)
    doc.title = "Test Plot"


def main():
    """Launch the server and connect to it.
    """
    print("Preparing a bokeh application.")
    io_loop = IOLoop.current()
    bokeh_app = Application(FunctionHandler(modify_doc))

    server = Server({"/": bokeh_app}, io_loop=io_loop)
    server.start()
    print("Opening Bokeh application on http://localhost:5006/")

    io_loop.add_callback(server.show, "/")
    io_loop.start()


main()

Этот файл может быть выполнен

$ python local_server.py

которые запускают сервер и автоматически запускают браузер для показа документа.

Точки входа и setup.py

Чтобы предоставить скрипт, который можно легко установить и вызвать с помощью setup.py. Рассмотрим следующую структуру папок:

project
├── setup.py
└── my_package
    ├── __init__.py
    └── local_server.py

Содержание setup.py:

from setuptools import setup

setup(
    name = "my_package",
    entry_points={
        "console_scripts": ["my_script = my_package.local_server:main"],
    },
)

При установке пакета с помощью

$ python setup.py install

Вы можете использовать звонок

$ my_script

запустить приложение bokeh и автоматически запустить браузер, отображающий документ.

Другие вопросы по тегам