Repository: dask/distributed

Issue:
pandas is now a mandatory dependency for dscheduler
If pandas is not installed I get an infinite loop with the following logs:

```
tornado.httpclient.HTTPError: HTTP 500: Internal Server Error
bokeh.util.tornado - ERROR - Error thrown from periodic callback: HTTPError(500, 'Internal Server Error', HTTPResponse(_body=None,buffer=<_io.BytesIO object at 0x7f17202a1e08>,code=500,effective_url='http://localhost:9786/tasks.json',error=HTTPError(...),headers=<tornado.httputil.HTTPHeaders object at 0x7f17204ffe48>,reason='Internal Server Error',request=<tornado.httpclient.HTTPRequest object at 0x7f1720578da0>,request_time=0.005105733871459961,time_info={}))
distributed.utils - ERROR - No module named 'pandas'
Traceback (most recent call last):
  File "/volatile/ogrisel/code/distributed/distributed/utils.py", line 229, in log_errors
    yield
  File "/volatile/ogrisel/code/distributed/distributed/http/scheduler.py", line 79, in get
    from ..diagnostics.scheduler import tasks
  File "/volatile/ogrisel/code/distributed/distributed/diagnostics/scheduler.py", line 6, in <module>
    import pandas as pd
ImportError: No module named 'pandas'
```

If think this is not intended? The diagnostics callback should probably be disabled when  pandas is not available, no?



Discussion:
We can definitely resolve this.  Fixing now.


Resolving patch:
diff --git a/distributed/diagnostics/scheduler.py b/distributed/diagnostics/scheduler.py
--- a/distributed/diagnostics/scheduler.py
+++ b/distributed/diagnostics/scheduler.py
@@ -3,7 +3,6 @@
 from datetime import datetime
 import os
 
-import pandas as pd
 from toolz import countby, concat, dissoc
 
 from ..utils import key_split
@@ -83,6 +82,7 @@ def scheduler_progress_df(d):
     in-memory       30  +++++++++++++++++
     total           70  ++++++++++++++++++++++++++++++++++++++++
     """
+    import pandas as pd
     d = d.copy()
     d['total'] = d.pop('tasks')
     names = ['waiting', 'ready', 'failed', 'processing', 'in-memory', 'total']
@@ -120,6 +120,7 @@ def worker_status_df(d):
     192.168.1.107       4   2000       [inc]
     192.168.1.108       4   1000  [add, inc]
     """
+    import pandas as pd
     names = ['ncores', 'bytes', 'processing']
     df = pd.DataFrame({k: d[k] for k in names}, columns=names)
     df['processing'] = df['processing'].apply(sorted)
diff --git a/distributed/formats/csv.py b/distributed/formats/csv.py
--- a/distributed/formats/csv.py
+++ b/distributed/formats/csv.py
@@ -3,8 +3,6 @@
 from io import BytesIO
 
 from dask import do
-from dask.dataframe import from_imperative
-import pandas as pd
 
 from .compression import compressors, decompressors
 
@@ -27,6 +25,7 @@ def bytes_read_csv(b, header, kwargs):
     See Also:
         distributed.formats.csv.read_csv
     """
+    import pandas as pd
     with log_errors():
         compression = kwargs.pop('compression', None)
         b2 = decompressors[compression](b)
@@ -67,6 +66,7 @@ def read_csv(block_lists, header, head, kwargs, lazy=True, collection=True,
     A dask.dataframe, or list of futures or values, depending on the value of
     lazy and collection.
     """
+    from dask.dataframe import from_imperative
     executor = default_executor(executor)
 
     dfs1 = [[do(bytes_read_csv)(blocks[0], '', kwargs)] +


Test patch:
diff --git a/distributed/formats/tests/test_csv.py b/distributed/formats/tests/test_csv.py
--- a/distributed/formats/tests/test_csv.py
+++ b/distributed/formats/tests/test_csv.py
@@ -1,17 +1,20 @@
-from distributed.compatibility import gzip_compress
-from distributed.utils_test import gen_cluster
-from distributed.formats.csv import read_csv, bytes_read_csv
-from distributed.executor import Future
+from __future__ import print_function, division, absolute_import
 
+from io import BytesIO
 
-import pandas.util.testing as tm
-import pandas as pd
-from tornado import gen
 import pytest
-from io import BytesIO
+pd = pytest.importorskip('pandas')
+dd = pytest.importorskip('dask.dataframe')
+
+import pandas.util.testing as tm
 from toolz import partition_all
+from tornado import gen
+
+from distributed.compatibility import gzip_compress
+from distributed.executor import Future
+from distributed.formats.csv import read_csv, bytes_read_csv
+from distributed.utils_test import gen_cluster
 
-dd = pytest.importorskip('dask.dataframe')
 
 
 files = {'2014-01-01.csv': (b'name,amount,id\n'
diff --git a/distributed/tests/test_collections.py b/distributed/tests/test_collections.py
--- a/distributed/tests/test_collections.py
+++ b/distributed/tests/test_collections.py
@@ -1,9 +1,12 @@
 from __future__ import print_function, division, absolute_import
 
-
 from datetime import timedelta
 import sys
 
+import pytest
+pytest.importorskip('numpy')
+pytest.importorskip('pandas')
+
 import dask
 import dask.dataframe as dd
 from distributed import Executor
@@ -17,7 +20,6 @@
 import numpy as np
 import pandas as pd
 import pandas.util.testing as tm
-import pytest
 from toolz import identity
 
 from tornado import gen