Repository: dask/distributed

Issue:
More convenient way to create the scheduler-file
The concept of a "scheduler file" is a nice, convenient way to share scheduler information when working on a system where you won't know the scheduler address a priori. I would like to suggest a simple method, probably on `Client`, that creates such a "scheduler file" with a simple interface like this:

```Python
from distributed import Client
client = Client()
client.to_scheduler_file('path-to-a-file.json')
```

then from another session one could easily connect to that same set of resources via:

```Python
from distributed import Client
client = Client(scheduler_file='path-to-a-file.json')
```

Under the hood this would just be something like 

```Python
json.dump(client.scheduler_info(), 'path-to-a-file.json', indent=2)
```


Discussion:

Resolving patch:
diff --git a/distributed/client.py b/distributed/client.py
--- a/distributed/client.py
+++ b/distributed/client.py
@@ -2767,6 +2767,33 @@ def scheduler_info(self, **kwargs):
         self.sync(self._update_scheduler_info)
         return self._scheduler_identity
 
+    def write_scheduler_file(self, scheduler_file):
+        """ Write the scheduler information to a json file.
+
+        This facilitates easy sharing of scheduler information using a file
+        system. The scheduler file can be used to instantiate a second Client
+        using the same scheduler.
+
+        Parameter
+        ---------
+        scheduler_file: str
+            Path to a write the scheduler file.
+
+        Examples
+        --------
+        >>> client = Client()
+        >>> client.write_scheduler_file('scheduler.json')
+        # connect to previous client's scheduler
+        >>> client2 = Client(scheduler_file='scheduler.json')
+        """
+        if self.scheduler_file:
+            raise ValueError('Scheduler file already set')
+        else:
+            self.scheduler_file = scheduler_file
+
+        with open(self.scheduler_file, 'w') as f:
+            json.dump(self.scheduler_info(), f, indent=2)
+
     def get_metadata(self, keys, default=no_default):
         """ Get arbitrary metadata from scheduler
 


Test patch:
diff --git a/distributed/tests/test_client.py b/distributed/tests/test_client.py
--- a/distributed/tests/test_client.py
+++ b/distributed/tests/test_client.py
@@ -40,7 +40,8 @@
 from distributed.metrics import time
 from distributed.scheduler import Scheduler, KilledWorker
 from distributed.sizeof import sizeof
-from distributed.utils import ignoring, mp_context, sync, tmp_text, tokey
+from distributed.utils import (ignoring, mp_context, sync, tmp_text, tokey,
+                               tmpfile)
 from distributed.utils_test import (cluster, slow, slowinc, slowadd, slowdec,
                                     randominc, inc, dec, div, throws, geninc, asyncinc,
                                     gen_cluster, gen_test, double, deep, popen,
@@ -3716,6 +3717,22 @@ def test_scheduler_info(loop):
             assert len(info['workers']) == 2
 
 
+def test_write_scheduler_file(loop):
+    with cluster() as (s, [a, b]):
+        with Client(s['address'], loop=loop) as c:
+            info = c.scheduler_info()
+            with tmpfile('json') as scheduler_file:
+                c.write_scheduler_file(scheduler_file)
+                with Client(scheduler_file=scheduler_file) as c2:
+                    info2 = c2.scheduler_info()
+                    assert c.scheduler.address == c2.scheduler.address
+
+                # test that a ValueError is raised if the scheduler_file
+                # attribute is already set
+                with pytest.raises(ValueError):
+                    c.write_scheduler_file(scheduler_file)
+
+
 def test_get_versions(loop):
     with cluster() as (s, [a, b]):
         with Client(s['address'], loop=loop) as c: