Repository: dask/distributed

Issue:
Bokeh is not listed in requirements.txt but seems needed
Bokeh is not listed in requirements.txt, but instantiating an Executor crashes from lack of bokeh:

<pre>
/home/varoquau/test.py in <module>()
     16     return {'error': sum(y) / n, 'param': param}
     17 
---> 18 e = Executor()
     19 error = e.map(test_model, [1, 2, 3, 4])
     20 error = e.gather(error)

/home/varoquau/.local/lib/python2.7/site-packages/distributed/executor.pyc in __init__(self, address, start, loop, timeout, set_as_default)
    276 
    277         if start:
--> 278             self.start(timeout=timeout)
    279 
    280     def __str__(self):

/home/varoquau/.local/lib/python2.7/site-packages/distributed/executor.pyc in start(self, **kwargs)
    304         self.loop.add_callback(pc.start)
    305         _global_executor[0] = self
--> 306         sync(self.loop, self._start, **kwargs)
    307         self.status = 'running'
    308 

/home/varoquau/.local/lib/python2.7/site-packages/distributed/utils.pyc in sync(loop, func, *args, **kwargs)
    114         e.wait(1000000)
    115     if error[0]:
--> 116         six.reraise(type(error[0]), error[0], traceback[0])
    117     else:
    118         return result[0]

/home/varoquau/.local/lib/python2.7/site-packages/distributed/utils.pyc in f()
    100     def f():
    101         try:
--> 102             result[0] = yield gen.maybe_future(func(*args, **kwargs))
    103         except Exception as exc:
    104             logger.exception(exc)

/usr/lib/python2.7/dist-packages/tornado/gen.pyc in run(self)
    868 
    869                     try:
--> 870                         value = future.result()
    871                     except Exception:
    872                         self.had_exception = True

/usr/lib/python2.7/dist-packages/tornado/concurrent.pyc in result(self, timeout)
    213             return self._result
    214         if self._exc_info is not None:
--> 215             raise_exc_info(self._exc_info)
    216         self._check_done()
    217         return self._result

/usr/lib/python2.7/dist-packages/tornado/gen.pyc in wrapper(*args, **kwargs)
    228                 try:
    229                     orig_stack_contexts = stack_context._state.contexts
--> 230                     yielded = next(result)
    231                     if stack_context._state.contexts is not orig_stack_contexts:
    232                         yielded = TracebackFuture()

/home/varoquau/.local/lib/python2.7/site-packages/distributed/executor.pyc in _start(self, timeout, **kwargs)
    320             from distributed.deploy import LocalCluster
    321             try:
--> 322                 self.cluster = LocalCluster(loop=self.loop, start=False)
    323             except (OSError, socket.error):
    324                 self.cluster = LocalCluster(scheduler_port=0, loop=self.loop,

/home/varoquau/.local/lib/python2.7/site-packages/distributed/deploy/local.pyc in __init__(self, n_workers, threads_per_worker, nanny, loop, start, scheduler_port, silence_logs, diagnostics_port, services, **kwargs)
     99         if diagnostics_port is not None:
    100             self.start_diagnostics_server(diagnostics_port,
--> 101                                           silence=silence_logs)
    102 
    103     def __str__(self):

/home/varoquau/.local/lib/python2.7/site-packages/distributed/deploy/local.pyc in start_diagnostics_server(self, port, show, silence)
    174                     io_loop=self.scheduler.loop)
    175             self.scheduler.services['http'].listen(0)
--> 176         from distributed.bokeh.application import BokehWebInterface
    177         self.diagnostics = BokehWebInterface(
    178                 tcp_port=self.scheduler.port,

/home/varoquau/.local/lib/python2.7/site-packages/distributed/bokeh/application.py in <module>()
      7 import sys
      8 
----> 9 import bokeh
     10 import distributed.bokeh
     11 from ..utils import ignoring

ImportError: No module named bokeh
</pre>



Discussion:

Resolving patch:
diff --git a/distributed/deploy/local.py b/distributed/deploy/local.py
--- a/distributed/deploy/local.py
+++ b/distributed/deploy/local.py
@@ -15,6 +15,8 @@
 from ..scheduler import Scheduler
 from ..worker import Worker, _ncores
 
+logger = logging.getLogger(__file__)
+
 
 class LocalCluster(object):
     """ Create local Scheduler and Workers
@@ -168,12 +170,17 @@ def start_diagnostics_server(self, port=8787, show=False,
 
             http://localhost:8787/status/
         """
+        try:
+            from distributed.bokeh.application import BokehWebInterface
+        except ImportError:
+            logger.info("To start diagnostics web server please install Bokeh")
+            return
+
         assert self.diagnostics is None
         if 'http' not in self.scheduler.services:
             self.scheduler.services['http'] = HTTPScheduler(self.scheduler,
                     io_loop=self.scheduler.loop)
             self.scheduler.services['http'].listen(0)
-        from distributed.bokeh.application import BokehWebInterface
         self.diagnostics = BokehWebInterface(
                 tcp_port=self.scheduler.port,
                 http_port=self.scheduler.services['http'].port,


Test patch: