2017-07-19 2 views
2

私は、パッケージ内にデプロイするbokeh0.12.6)ユーティリティを使用して、対話的なデータ操作を行っています。ユーザーは、bokehサーバーを起動し、ブラウザーでアプリケーションを起動し、タブまたはブラウザーを閉じたときにサーバーを停止させるルーチンを実行することができるということです(module.utility())。bokehサーバーをプログラムで実行すると、ブラウザにローカルで表示されます

bokeh serve --show myappを実行するとアプリケーションが正常に起動しますが、以下で説明するメソッドを使用してローカルホストに接続するとハングアップします。私はハンドラを点検しました、すべてが見えるように見えます。

これは合理的なことですか、私はそれについて正しく行っていますか?

ディレクトリ形式./myappvenv/lib/python3.5/site-packages/mymoduleなどに存在します

<installed module path>/myapp 
└── main.py 

main.py

from bokeh.io import curdoc 
from bokeh.layouts import column 
from bokeh.plotting import figure 
from bokeh.models.sources import ColumnDataSource 

source = ColumnDataSource(dict(x=list(range(5)), y=list(range(5)))) 

p = figure(width=300, height=300, tools=[], toolbar_location=None) 
p.line(x='x', y='y', source=source) 

curdoc().add_root(column(p, sizing_mode='scale_width')) 

実行スクリプト

def run_single_server(abs_app_path, port=5000): 
    '''Run bokeh application for single session from server`''' 
    from bokeh.application import Application 
    from bokeh.application.handlers import DirectoryHandler 
    from bokeh.server.server import Server 
    import os 

    app_name = os.path.split(abs_app_path)[1] 
    url = '/{}'.format(app_name) 

    # Start a bokeh server 
    apps = {url:Application(DirectoryHandler(filename=abs_app_path))} 
    server = Server(apps, port=port) 
    server.start() 
    server.show(url) 

    # somehow wait for session to end, perhaps using `server_lifecycle.py` 

    server.stop() 

    return 

def utility(): 
    import mymodule 

    module_path = os.path.split(mymodule.__file__)[0] 
    abs_app_path = os.path.join(module_path, 'myapp') 

    run_single_server(abs_app_path, port=5000) 

    return 

はおそらくメイン__init__.pyでそのルーチンを持っており、それがこのように動作します:

import mymodule 
mymodule.utility() 

# 1. Browser launches 
# 2. user does stuff 
# 3. user closes window 
# 4. bokeh server is shutdown 

更新 私は、build_single_handler_applicationルーチンを発見していることを試してみましたそれはまた、ハングアップするように見えます。

from bokeh.command.util import build_single_handler_application 
import os 

app_name = os.path.split(abs_app_path)[1] 
url = '/{}'.format(app_name) 

# Start a bokeh server 
apps = build_single_handler_application(abs_app_path) 

答えて

2

私にはいくつか問題があるようです。私は、メールグループhereで見つけたいくつかのコードを、私の使用事例のために見つけて適応させました。

1)サーバーの起動、2)アプリケーションのURLをwebbrowserで起動し、3)閉じられた接続を確認してシャットダウンすることで、すべてを稼働させることができました。

tornadoサーバインスタンスを開始することはできませんが、私が採用したフラスコの例ではそうだったようですが、私はここで満足しています。

注:この例では、単一ファイルのアプリケーションを使用していますが、ディレクトリ形式のアプリケーションのパスも渡すことができます。

def create_bokeh_server(io_loop, files, argvs, host, port): 
    '''Start bokeh server with applications paths''' 
    from bokeh.server.server import Server 
    from bokeh.command.util import build_single_handler_applications 

    # Turn file paths into bokeh apps 
    apps = build_single_handler_applications(files, argvs) 

    # kwargs lifted from bokeh serve call to Server, with created io_loop 
    kwargs = { 
     'io_loop':io_loop, 
     'generate_session_ids':True, 
     'redirect_root':True, 
     'use_x_headers':False, 
     'secret_key':None, 
     'num_procs':1, 
     'host': host, 
     'sign_sessions':False, 
     'develop':False, 
     'port':port, 
     'use_index':True 
    } 
    server = Server(apps,**kwargs) 

    return server 


def run_single_app(files, port=5000, new='tab'): 

    def start_bokeh(io_loop): 
     '''Start the `io_loop`''' 
     io_loop.start() 
     return None 

    def launch_app(host, app_name, new): 
     '''Lauch app in browser 

     Ideally this would `bokeh.util.browser.view()`, but it doesn't work 
     ''' 
     import webbrowser 

     # Map method strings to webbrowser method 
     options = {'current':0, 'window':1, 'tab':2} 

     # Concatenate url and open in browser, creating a session 
     app_url = 'http://{}/{}'.format(host, app_name) 
     print('Opening `{}` in browser'.format(app_url)) 
     webbrowser.open(app_url, new=options[new]) 

     return None 

    def server_loop(server, io_loop): 
     '''Check connections once session created and close on disconnect''' 
     import time 

     connected = [True,] 
     session_loaded = False 
     while any(connected): 

      # Check if no session started on server 
      sessions = server.get_sessions() 
      if not session_loaded: 
       if sessions: 
        session_loaded = True 
      # Once 1+ sessions started, check for no connections 
      else: 
       # List of bools for each session 
       connected = [True,]*len(sessions) 
       # Set `connected` item false no connections on session 
       for i in range(len(sessions)): 
        if sessions[i].connection_count == 0: 
         connected[i] = False 
      # Keep the pace down 
      time.sleep(2) 

     # Stop server once opened session connections closed 
     io_loop.stop() 

     return None 

    import os 
    import threading 
    import tornado.ioloop 
    import tornado.autoreload 
    import time 

    # Initialize some values, sanatize the paths to the bokeh plots 
    argvs = {} 
    app_names = [] 
    for path in files: 
     argvs[path] = None 
     app_names.append(os.path.splitext(os.path.split(path)[1])[0]) 

    # Concate hostname/port for creating handlers, launching apps 
    host = 'localhost:{}'.format(port) 

    # Initialize the tornado server 
    io_loop = tornado.ioloop.IOLoop.instance() 
    tornado.autoreload.start(io_loop) 

    # Add the io_loop to the bokeh server 
    server = run_bokeh_server(io_loop, files, argvs, host, port) 

    print('Starting the server on {}'.format(host)) 
    args = (io_loop,) 
    th_startup = threading.Thread(target=start_bokeh, args=args) 
    th_startup.start() 

    # Launch each application in own tab or window 
    th_launch = [None,]*len(app_names) 
    for i in range(len(app_names)): 
     args = (host, app_names[i], new) 
     th_launch[i] = threading.Thread(target=launch_app, args=args) 
     th_launch[i].start() 
     # Delay to allow tabs to open in same browser window 
     time.sleep(2) 

    # Run session connection test, then stop `io_loop` 
    args = (server, io_loop) 
    th_shutdown = threading.Thread(target=server_loop, args=args) 
    th_shutdown.start() 

    return None 

if __name__ == "__main__": 

import os 
files = [os.path.join('bokeh', fname) for fname in ['ex1.py','ex2.py']] 
run_single_app(files, port=5006) 
関連する問題