【问题标题】:Entry point for a bokeh server散景服务器的入口点
【发布时间】:2017-08-14 23:09:26
【问题描述】:

我提供了一个工具作为我的 python 包的一部分,它使用散景可视化参数空间。启动它的正常方式是:

$ 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 中,我已经指定了 main 方法的入口点:

安装程序.py
from setuptools import setup, find_packages

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

但是,我发现启动散景服务器并显示界面的唯一方法是创建另一个像这样的 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 提供这种入口点,或者是否有其他方法可以实现这种行为?

【问题讨论】:

    标签: python setuptools bokeh setup.py


    【解决方案1】:

    为了扩展the answer of @jxramos,我修改了页面上给出的standalone embed example。通过在 main 函数中自己管理 tornado IO 循环,您可以使散景脚本的行为类似于 普通 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'
          ]
    },
    [...]
    

    普通版

    以下是我从我编写的文档示例中移植过来的更完整示例。由于文档正在逐步淘汰,我认为它更适合作为此答案的一部分。

    带有控制台入口点的本地散景服务器

    要允许像 普通 .py 文件一样执行散景应用程序,您需要在应用程序中处理龙卷风 IOloop,如 here 所述。像这样的独立散景应用程序可用于在setup.py 中实现控制台脚本入口点。 但是,这需要散景版本 >= 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
    

    启动散景应用程序并自动启动显示文档的浏览器。

    【讨论】:

    • 非常酷,我仍在寻找有关散景应用程序对象与文档关系的背景信息,到目前为止,在我看来它是 1:1 的关系。因此,如果我想要相同数据的两个视图,我需要两个应用程序。这听起来与您迄今为止收集的内容准确吗?在词汇表中,我们有“应用程序:Bokeh 应用程序是渲染的 Bokeh 文档,在浏览器中运行。”,然后是“文档:Bokeh 应用程序的组织数据结构。文档包含渲染交互所需的所有 Bokeh 模型和数据浏览器中的可视化或应用程序。”
    • @jxramos 我也很困惑 ;) 我认为没有什么能阻止您在一个文档中使用多个图表(我猜是在一个应用程序中呈现?)就像在 heatmap example 中一样。只要您使用相同的基础数据源,更改 sliders example 中的数据应该会影响所有关联的图表。 linking plots 看起来也很整洁。
    • 再看一遍,我注意到 Server 将字典作为参数,所以我查看了源代码,其中有一个有用的评论...applications (dict of str: bokeh.application.Application) or bokeh.application.Application: mapping from URL paths to Application instances, or a single Application to put at the root URL The Application is a factory for Document, with a new Document initialized for each Session. Each application should be identified by a path meant to go in a URL, like "/" or "/foo"
    • 我们如何允许不同的来源?相当于非单机版的“bokeh serve script.py --allow-websocket-origin foo.com:8081”
    【解决方案2】:

    如果我没记错的话,您可以使用 Embedding Bokeh Server as a Library 文档中介绍的嵌入式服务器路由。在文档的该部分之后,有一条关于使用散景服务器客户端 api 的后续行。听起来他们正在研究未来连接到服务器的更多方法,以及他们讨论用例的部分。

    【讨论】:

    • 感谢您的指点。我找到了一种使用standalone embed example 使其工作的方法。
    • 如何使用这些方法中的任何一种来允许不同的 websocket 源?类似于“bokeh serve app_script.py --allow-websocket-origin foo.com:8081”命令
    • @dnh37 查看我提供的链接中包含的链接示例。搜索线server = Server({'/bkapp': modify_doc}, allow_websocket_origin=["localhost:8000"]);你基本上在Server构造函数中定义它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多