Repository: dask/dask

Issue:
Error in calling dask.multiprocessing.get
I installed dask,
dask                      0.9.0                    py27_2    conda-forge

and following the tutorial, I get error.

``` python
In [5]: from dask.multiprocessing import get

In [6]: results = get(dsk, ['print1', 'print2'])
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-a0eeda767e16> in <module>()
----> 1 results = get(dsk, ['print1', 'print2'])

/home/antgr/anaconda2/lib/python2.7/site-packages/dask/multiprocessing.pyc in get(dsk, keys, optimizations, num_workers, func_loads, func_dumps, **kwargs)
     76         # Run
     77         result = get_async(apply_async, len(pool._pool), dsk3, keys,
---> 78                            queue=queue, get_id=_process_get_id, **kwargs)
     79     finally:
     80         if cleanup:

/home/antgr/anaconda2/lib/python2.7/site-packages/dask/async.pyc in get_async(apply_async, num_workers, dsk, result, cache, queue, get_id, raise_on_exception, rerun_exceptions_locally, callbacks, **kwargs)
    492             f(key, res, dsk, state, worker_id)
    493         while state['ready'] and len(state['running']) < num_workers:
--> 494             fire_task()
    495 
    496     # Final reporting

/home/antgr/anaconda2/lib/python2.7/site-packages/dask/async.pyc in fire_task()
    463         # Submit
    464         apply_async(execute_task, args=[key, dsk[key], data, queue,
--> 465                                         get_id, raise_on_exception])
    466 
    467     # Seed initial tasks into the thread pool

/home/antgr/anaconda2/lib/python2.7/site-packages/toolz/functoolz.pyc in __call__(self, *args, **kwargs)
    217     def __call__(self, *args, **kwargs):
    218         try:
--> 219             return self._partial(*args, **kwargs)
    220         except TypeError:
    221             # If there was a genuine TypeError

/home/antgr/anaconda2/lib/python2.7/site-packages/dask/multiprocessing.pyc in pickle_apply_async(apply_async, func, args, kwds, func_loads, func_dumps)
     96     dumps = func_dumps or _globals.get('func_dumps') or _dumps
     97     sfunc = dumps(func)
---> 98     sargs = dumps(args)
     99     skwds = dumps(kwds)
    100     return apply_async(curry(apply_func, loads=func_loads),

/home/antgr/anaconda2/lib/python2.7/site-packages/dask/multiprocessing.pyc in _dumps(x)
     23 
     24 def _dumps(x):
---> 25     return cloudpickle.dumps(x, protocol=pickle.HIGHEST_PROTOCOL)
     26 
     27 _loads = pickle.loads

/home/antgr/anaconda2/lib/python2.7/site-packages/cloudpickle/cloudpickle.pyc in dumps(obj, protocol)
    627 
    628     cp = CloudPickler(file,protocol)
--> 629     cp.dump(obj)
    630 
    631     return file.getvalue()

/home/antgr/anaconda2/lib/python2.7/site-packages/cloudpickle/cloudpickle.pyc in dump(self, obj)
    105         self.inject_addons()
    106         try:
--> 107             return Pickler.dump(self, obj)
    108         except RuntimeError as e:
    109             if 'recursion' in e.args[0]:

/home/antgr/anaconda2/lib/python2.7/pickle.pyc in dump(self, obj)
    222         if self.proto >= 2:
    223             self.write(PROTO + chr(self.proto))
--> 224         self.save(obj)
    225         self.write(STOP)
    226 

/home/antgr/anaconda2/lib/python2.7/pickle.pyc in save(self, obj)
    284         f = self.dispatch.get(t)
    285         if f:
--> 286             f(self, obj) # Call unbound method with explicit self
    287             return
    288 

/home/antgr/anaconda2/lib/python2.7/pickle.pyc in save_list(self, obj)
    604 
    605         self.memoize(obj)
--> 606         self._batch_appends(iter(obj))
    607 
    608     dispatch[ListType] = save_list

/home/antgr/anaconda2/lib/python2.7/pickle.pyc in _batch_appends(self, items)
    637                 write(MARK)
    638                 for x in tmp:
--> 639                     save(x)
    640                 write(APPENDS)
    641             elif n:

/home/antgr/anaconda2/lib/python2.7/pickle.pyc in save(self, obj)
    284         f = self.dispatch.get(t)
    285         if f:
--> 286             f(self, obj) # Call unbound method with explicit self
    287             return
    288 

/home/antgr/anaconda2/lib/python2.7/pickle.pyc in save_tuple(self, obj)
    552         if n <= 3 and proto >= 2:
    553             for element in obj:
--> 554                 save(element)
    555             # Subtle.  Same as in the big comment below.
    556             if id(obj) in memo:

/home/antgr/anaconda2/lib/python2.7/pickle.pyc in save(self, obj)
    284         f = self.dispatch.get(t)
    285         if f:
--> 286             f(self, obj) # Call unbound method with explicit self
    287             return
    288 

/home/antgr/anaconda2/lib/python2.7/pickle.pyc in save_tuple(self, obj)
    566         write(MARK)
    567         for element in obj:
--> 568             save(element)
    569 
    570         if id(obj) in memo:

/home/antgr/anaconda2/lib/python2.7/pickle.pyc in save(self, obj)
    284         f = self.dispatch.get(t)
    285         if f:
--> 286             f(self, obj) # Call unbound method with explicit self
    287             return
    288 

/home/antgr/anaconda2/lib/python2.7/site-packages/cloudpickle/cloudpickle.pyc in save_builtin_function(self, obj)
    328         if obj.__module__ == "__builtin__":
    329             return self.save_global(obj)
--> 330         return self.save_function(obj)
    331     dispatch[types.BuiltinFunctionType] = save_builtin_function
    332 

/home/antgr/anaconda2/lib/python2.7/site-packages/cloudpickle/cloudpickle.pyc in save_function(self, obj, name)
    201         # reference (as is done in default pickler), via save_function_tuple.
    202         if (islambda(obj)
--> 203                 or getattr(obj.__code__, 'co_filename', None) == '<stdin>'
    204                 or themodule is None):
    205             self.save_function_tuple(obj)

AttributeError: 'builtin_function_or_method' object has no attribute '__code__'
```



Discussion:
It looks like the issue is in cloudpickle, dealing with serialization of builtin functions. Two things would help with diagnosing this:
- What version of cloudpickle do you have installed? Just do:

``` python
import cloudpickle
cloudpickle.__version__
```
- What is `dsk`? A reproducible example will be helpful.

Thanks.
version of cloudpickle:

In [1]: import cloudpickle
In [2]: cloudpickle.**version**
Out[2]: '0.2.1'

I used this tutorial
http://dask.pydata.org/en/latest/optimize.html,

> > > from **future** import print_function
> > > 
> > > def print_and_return(string):
> > >         print(string)
> > >         return string
> > > 
> > > format_str = 'word list has {0} occurrences of {1}, out of {2} words'
> > > 
> > > dsk = {'words': 'apple orange apple pear orange pear pear',
> > >            'nwords': (len, (str.split, 'words')),
> > >            'val1': 'orange',
> > >            'val2': 'apple',
> > >            'val3': 'pear',
> > >            'count1': (str.count, 'words', 'val1'),
> > >            'count2': (str.count, 'words', 'val2'),
> > >            'count3': (str.count, 'words', 'val3'),
> > >            'out1': (format_str.format, 'count1', 'val1', 'nwords'),
> > >            'out2': (format_str.format, 'count2', 'val2', 'nwords'),
> > >            'out3': (format_str.format, 'count3', 'val3', 'nwords'),
> > >            'print1': (print_and_return, 'out1'),
> > >            'print2': (print_and_return, 'out2'),
> > >            'print3': (print_and_return, 'out3')}
> > > 
> > > from dask.multiprocessing import get
> > > 
> > > results = get(dsk, ['print1', 'print2'])    <---- here is the error for me.
> > > word list has 3 occurrences of pear, out of 7 words
> > > word list has 2 occurrences of apple, out of 7 words
> > > word list has 2 occurrences of orange, out of 7 words

etc.


Resolving patch:
diff --git a/dask/async.py b/dask/async.py
--- a/dask/async.py
+++ b/dask/async.py
@@ -385,10 +385,6 @@ def get_async(apply_async, num_workers, dsk, result, cache=None,
     specific ``get`` method that walks through the dask array with parallel
     workers, avoiding repeat computation and minimizing memory use.
 
-    This function evaluates the entire graph, regardless of the given output
-    keys.  You may want to cull your graph ahead of time with
-    ``dask.optimize.cull``.
-
     Parameters
     ----------
 


Test patch: