带有交互的散景开发工作流程

bokeh development workflow with interaction

我正在使用

开发可视化
% bokeh serve --show myapp.py 

问题是,当我更改 myapp.py 时,我必须终止上面的命令并重新启动它。这种开发有更好的工作流程吗?

谢谢!

还没有。从 Bokeh 0.11.1 开始(很快也会 0.12),这是计划中的,但仍然开放,feature request There are only a few folks working a huge pile of work for Bokeh. New contributors can help accelerate new features and fixes. If you're able to help, please reach out to us on the project gitter channel

我无法充分理解散景的内部结构,无法更好地完成这项工作,但这里有一个 hacky 脚本,无论如何都能满足我的要求。

# bokeh_watcher.py
#
# Watches specific files in directory and restarts bokeh server upon change.
#
#   % python bokeh_watcher filename.py
#
# Note that you stil have to navigate your browser to localhost:5006/filename
# to see your Bokeh visualization and you might have to refresh the browser. 

import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import RegexMatchingEventHandler
from bokeh.command.bootstrap import main
import multiprocessing
import os
JOBS = []
FILE = []

def spawn_bokeh(args):
    main(args)

class BokehHandler(RegexMatchingEventHandler):
    '''
    kills and restarts bokeh server upon filechange.
    '''
    def on_modified(self, event):
        super(BokehHandler, self).on_modified(event)
        what = 'directory' if event.is_directory else 'file'
        logging.info("Modified %s: %s"% (what, event.src_path))
        p=JOBS.pop()
        p.terminate()
        time.sleep(1) # time to die
        logging.info('terminated')
        logging.info('initiating restart')
        p = multiprocessing.Process(target=spawn_bokeh,
                                    args=(self.args,))
        p.start()
        JOBS.append(p)

if __name__ == "__main__":
    here = os.path.realpath(__file__)
    fullpathname=os.path.dirname(here)+os.sep+sys.argv[1]
    # local logger
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    filemod_handler = BokehHandler(['.*%s'%(sys.argv[1])])
    filemod_handler.args = ['','serve',fullpathname, '--log-level','info'] 
    # fire up bokeh server
    p = multiprocessing.Process(target=spawn_bokeh,args=(filemod_handler.args,))
    p.start()
    # store object in global for later
    JOBS.append(p)
    observer = Observer()
    observer.schedule(filemod_handler, '.', recursive=False)
    observer.start()
    try:
        while True:
            time.sleep(3)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()