# Buggy code
def spawn(func, args=(), kwargs=None, retry_when_fail=True, n_output=None):
    """
    Spawn a function and return a Mars Object which can be executed later.

    Parameters
    ----------
    func : function
        Function to spawn.
    args: tuple
       Args to pass to function
    kwargs: dict
       Kwargs to pass to function
    retry_when_fail: bool, default True
       If True, retry when function failed.
    n_output: int
       Count of outputs for the function

    Returns
    -------
    Object
        Mars Object.

    Examples
    --------
    >>> import mars.remote as mr
    >>> def inc(x):
    >>>     return x + 1
    >>>
    >>> result = mr.spawn(inc, args=(0,))
    >>> result
    Object <op=RemoteFunction, key=e0b31261d70dd9b1e00da469666d72d9>
    >>> result.execute().fetch()
    1

    List of spawned functions can be converted to :class:`mars.remote.ExecutableTuple`,
    and `.execute()` can be called to run together.

    >>> results = [mr.spawn(inc, args=(i,)) for i in range(10)]
    >>> mr.ExecutableTuple(results).execute().fetch()
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    Mars Object returned by :meth:`mars.remote.spawn` can be treated
    as arguments for other spawn functions.

    >>> results = [mr.spawn(inc, args=(i,)) for i in range(10)]   # list of spawned functions
    >>> def sum_all(xs):
            return sum(xs)
    >>> mr.spawn(sum_all, args=(results,)).execute().fetch()
    55

    inside a spawned function, new functions can be spawned.

    >>> def driver():
    >>>     results = [mr.spawn(inc, args=(i,)) for i in range(10)]
    >>>     return mr.ExecutableTuple(results).execute().fetch()
    >>>
    >>> mr.spawn(driver).execute().fetch()
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    Mars tensor, DataFrame and so forth is available in spawned functions as well.

    >>> import mars.tensor as mt
    >>> def driver2():
    >>>     t = mt.random.rand(10, 10)
    >>>     return t.sum().to_numpy()
    >>>
    >>> mr.spawn(driver2).execute().fetch()
    52.47844223908132

    Argument of `n_output` can indicate that the spawned function will return multiple outputs.
    This is important when some of the outputs may be passed to different functions.

    >>> def triage(alist):
    >>>     ret = [], []
    >>>     for i in alist:
    >>>         if i < 0.5:
    >>>             ret[0].append(i)
    >>>         else:
    >>>             ret[1].append(i)
    >>>     return ret
    >>>
    >>> def sum_all(xs):
    >>>     return sum(xs)
    >>>
    >>> l = [0.4, 0.7, 0.2, 0.8]
    >>> la, lb = mr.spawn(triage, args=(l,), n_output=2)
    >>>
    >>> sa = mr.spawn(sum_all, args=(la,))
    >>> sb = mr.spawn(sum_all, args=(lb,))
    >>> mr.ExecutableTuple([sa, sb]).execute().fetch()
    >>> [0.6000000000000001, 1.5]
    """
    if not isinstance(args, tuple):
        args = [args]
    else:
        args = list(args)
    if kwargs is None:
        kwargs = dict()
    if not isinstance(kwargs, dict):
        raise TypeError("kwargs has to be a dict")

    op = RemoteFunction(
        function=func,
        function_args=args,
        function_kwargs=kwargs,
        retry_when_fail=retry_when_fail,
        n_output=n_output,
    )
    return op()


# Traceback (ValueError)
In [1]: import mars.dataframe as md

In [2]: from mars.deploy.local import new_cluster

In [3]: cluster = new_cluster()
WARNING: Logging before InitGoogleLogging() is written to STDERR
I0710 12:01:39.413233 286952896 store.cc:1149] Allowing the Plasma store to use up to 3.43597GB of memory.
I0710 12:01:39.414255 286952896 store.cc:1176] Starting object store with directory /tmp and huge page support disabled

In [4]: import mars.tensor as mt

In [5]: df = md.DataFrame(mt.random.rand(10, 3))

In [6]: df.execute()
Out[6]:
0         1         2
0  0.212577  0.758511  0.148990
1  0.525289  0.382298  0.331657
2  0.821829  0.991404  0.504818
3  0.910740  0.971152  0.915968
4  0.540863  0.289341  0.546004
5  0.869099  0.257637  0.282307
6  0.738262  0.636345  0.717278
7  0.064604  0.481792  0.356584
8  0.598765  0.156633  0.140831
9  0.873232  0.527147  0.247436

In [7]: def f(in_df):
...:     return in_df.sum().to_pandas()
...:

In [8]: import mars.remote as mr

In [9]: mr.spawn(f, args=(df,)).execute()
Unexpected exception occurred in ExecutionActor.execute_graph. graph_key='6ca5f502ce0c9fbccecc434fde3fbe75'
Traceback (most recent call last):
File "/Users/qinxuye/Workspace/mars/mars/utils.py", line 353, in _wrapped
return func(*args, **kwargs)
File "/Users/qinxuye/Workspace/mars/mars/worker/execution.py", line 481, in execute_graph
no_prepare_chunk_keys=io_meta.get('no_prepare_chunk_keys') or set(),
File "/Users/qinxuye/Workspace/mars/mars/worker/execution.py", line 57, in __init__
graph = self.graph = deserialize_graph(graph_serialized)
File "/Users/qinxuye/Workspace/mars/mars/utils.py", line 283, in deserialize_graph
return graph_cls.from_pb(g)
File "mars/graph.pyx", line 426, in mars.graph.DirectedGraph.from_pb
File "mars/serialize/core.pyx", line 683, in mars.serialize.core.Serializable.from_pb
File "mars/serialize/core.pyx", line 667, in mars.serialize.core.Serializable.deserialize
File "mars/serialize/core.pyx", line 810, in mars.serialize.core.Provider.deserialize_model
File "mars/serialize/core.pyx", line 157, in mars.serialize.core.Field.deserialize
File "mars/serialize/pbserializer.pyx", line 874, in mars.serialize.pbserializer.ProtobufSerializeProvider.deserialize_field
File "mars/serialize/pbserializer.pyx", line 839, in mars.serialize.pbserializer.ProtobufSerializeProvider._deserial_reference_value
File "mars/serialize/core.pyx", line 731, in mars.serialize.core.AttributeAsDict.deserialize
File "mars/serialize/pbserializer.pyx", line 972, in mars.serialize.pbserializer.ProtobufSerializeProvider.deserialize_attribute_as_dict
File "mars/serialize/core.pyx", line 157, in mars.serialize.core.Field.deserialize
File "mars/serialize/pbserializer.pyx", line 878, in mars.serialize.pbserializer.ProtobufSerializeProvider.deserialize_field
File "mars/serialize/pbserializer.pyx", line 293, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_list
File "mars/serialize/pbserializer.pyx", line 812, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_value
File "mars/serialize/pbserializer.pyx", line 802, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_untyped_value
File "mars/serialize/pbserializer.pyx", line 223, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_function
File "/Users/qinxuye/Workspace/mars/mars/remote/core.py", line 46, in __setstate__
chunk = ci[0]().new_chunk(None, _key=ci[1], _id=ci[2], kws=[ci[3]])
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 347, in new_chunk
return self.new_chunks(inputs, kws=kws, **kw)[0]
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 341, in new_chunks
return self._new_chunks(inputs, kws=kws, **kwargs)
File "/Users/qinxuye/Workspace/mars/mars/dataframe/fetch/core.py", line 39, in _new_chunks
return super()._new_chunks(inputs, kws=kws, **kw)
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 315, in _new_chunks
chunk = self._create_chunk(j, index, **create_chunk_kw)
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 283, in _create_chunk
raise ValueError('output_type should be specified')
ValueError: output_type should be specified
Unhandled exception in promise call
Traceback (most recent call last):
File "/Users/qinxuye/Workspace/mars/mars/promise.py", line 372, in _wrapped
return func(*args, **kwargs)
File "/Users/qinxuye/Workspace/mars/mars/utils.py", line 353, in _wrapped
return func(*args, **kwargs)
File "/Users/qinxuye/Workspace/mars/mars/worker/execution.py", line 481, in execute_graph
no_prepare_chunk_keys=io_meta.get('no_prepare_chunk_keys') or set(),
File "/Users/qinxuye/Workspace/mars/mars/worker/execution.py", line 57, in __init__
graph = self.graph = deserialize_graph(graph_serialized)
File "/Users/qinxuye/Workspace/mars/mars/utils.py", line 283, in deserialize_graph
return graph_cls.from_pb(g)
File "mars/graph.pyx", line 426, in mars.graph.DirectedGraph.from_pb
File "mars/serialize/core.pyx", line 683, in mars.serialize.core.Serializable.from_pb
File "mars/serialize/core.pyx", line 667, in mars.serialize.core.Serializable.deserialize
File "mars/serialize/core.pyx", line 810, in mars.serialize.core.Provider.deserialize_model
File "mars/serialize/core.pyx", line 157, in mars.serialize.core.Field.deserialize
File "mars/serialize/pbserializer.pyx", line 874, in mars.serialize.pbserializer.ProtobufSerializeProvider.deserialize_field
File "mars/serialize/pbserializer.pyx", line 839, in mars.serialize.pbserializer.ProtobufSerializeProvider._deserial_reference_value
File "mars/serialize/core.pyx", line 731, in mars.serialize.core.AttributeAsDict.deserialize
File "mars/serialize/pbserializer.pyx", line 972, in mars.serialize.pbserializer.ProtobufSerializeProvider.deserialize_attribute_as_dict
File "mars/serialize/core.pyx", line 157, in mars.serialize.core.Field.deserialize
File "mars/serialize/pbserializer.pyx", line 878, in mars.serialize.pbserializer.ProtobufSerializeProvider.deserialize_field
File "mars/serialize/pbserializer.pyx", line 293, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_list
File "mars/serialize/pbserializer.pyx", line 812, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_value
File "mars/serialize/pbserializer.pyx", line 802, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_untyped_value
File "mars/serialize/pbserializer.pyx", line 223, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_function
File "/Users/qinxuye/Workspace/mars/mars/remote/core.py", line 46, in __setstate__
chunk = ci[0]().new_chunk(None, _key=ci[1], _id=ci[2], kws=[ci[3]])
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 347, in new_chunk
return self.new_chunks(inputs, kws=kws, **kw)[0]
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 341, in new_chunks
return self._new_chunks(inputs, kws=kws, **kwargs)
File "/Users/qinxuye/Workspace/mars/mars/dataframe/fetch/core.py", line 39, in _new_chunks
return super()._new_chunks(inputs, kws=kws, **kw)
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 315, in _new_chunks
chunk = self._create_chunk(j, index, **create_chunk_kw)
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 283, in _create_chunk
raise ValueError('output_type should be specified')
ValueError: output_type should be specified
Attempt 1: Unexpected error ValueError occurred in executing operand 6ca5f502ce0c9fbccecc434fde3fbe75 in 0.0.0.0:40516
Traceback (most recent call last):
File "/Users/qinxuye/Workspace/mars/mars/promise.py", line 372, in _wrapped
return func(*args, **kwargs)
File "/Users/qinxuye/Workspace/mars/mars/utils.py", line 353, in _wrapped
return func(*args, **kwargs)
File "/Users/qinxuye/Workspace/mars/mars/worker/execution.py", line 481, in execute_graph
no_prepare_chunk_keys=io_meta.get('no_prepare_chunk_keys') or set(),
File "/Users/qinxuye/Workspace/mars/mars/worker/execution.py", line 57, in __init__
graph = self.graph = deserialize_graph(graph_serialized)
File "/Users/qinxuye/Workspace/mars/mars/utils.py", line 283, in deserialize_graph
return graph_cls.from_pb(g)
File "mars/graph.pyx", line 426, in mars.graph.DirectedGraph.from_pb
return cls.deserialize(SerializableGraph.from_pb(pb_obj))
File "mars/serialize/core.pyx", line 683, in mars.serialize.core.Serializable.from_pb
return cls.deserialize(provider, obj)
File "mars/serialize/core.pyx", line 667, in mars.serialize.core.Serializable.deserialize
obj = provider.deserialize_model(cls, obj, callbacks, key_to_instance)
File "mars/serialize/core.pyx", line 810, in mars.serialize.core.Provider.deserialize_model
field.deserialize(self, model_instance, obj, callbacks, key_to_instance)
File "mars/serialize/core.pyx", line 157, in mars.serialize.core.Field.deserialize
return provider.deserialize_field(self, model_instance, obj, callbacks, key_to_instance)
File "mars/serialize/pbserializer.pyx", line 874, in mars.serialize.pbserializer.ProtobufSerializeProvider.deserialize_field
value = [self._deserial_reference_value(
File "mars/serialize/pbserializer.pyx", line 839, in mars.serialize.pbserializer.ProtobufSerializeProvider._deserial_reference_value
return model.deserialize(self, f_obj, callbacks, key_to_instance)
File "mars/serialize/core.pyx", line 731, in mars.serialize.core.AttributeAsDict.deserialize
obj = provider.deserialize_attribute_as_dict(
File "mars/serialize/pbserializer.pyx", line 972, in mars.serialize.pbserializer.ProtobufSerializeProvider.deserialize_attribute_as_dict
it_field.deserialize(self, model_instance, AttrWrapper(d_obj),
File "mars/serialize/core.pyx", line 157, in mars.serialize.core.Field.deserialize
return provider.deserialize_field(self, model_instance, obj, callbacks, key_to_instance)
File "mars/serialize/pbserializer.pyx", line 878, in mars.serialize.pbserializer.ProtobufSerializeProvider.deserialize_field
value = self._get_list(field_obj, field.type, callbacks, field.weak_ref)
File "mars/serialize/pbserializer.pyx", line 293, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_list
val = self._get_value(it_obj, tp.type if tp is not None else tp,
File "mars/serialize/pbserializer.pyx", line 812, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_value
return self._get_untyped_value(obj, callbacks, weak_ref)
File "mars/serialize/pbserializer.pyx", line 802, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_untyped_value
return ref(self._get_function(obj))
File "mars/serialize/pbserializer.pyx", line 223, in mars.serialize.pbserializer.ProtobufSerializeProvider._get_function
return cloudpickle.loads(x) if x is not None and len(x) > 0 else None
File "/Users/qinxuye/Workspace/mars/mars/remote/core.py", line 46, in __setstate__
chunk = ci[0]().new_chunk(None, _key=ci[1], _id=ci[2], kws=[ci[3]])
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 347, in new_chunk
return self.new_chunks(inputs, kws=kws, **kw)[0]
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 341, in new_chunks
return self._new_chunks(inputs, kws=kws, **kwargs)
File "/Users/qinxuye/Workspace/mars/mars/dataframe/fetch/core.py", line 39, in _new_chunks
return super()._new_chunks(inputs, kws=kws, **kw)
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 315, in _new_chunks
chunk = self._create_chunk(j, index, **create_chunk_kw)
File "/Users/qinxuye/Workspace/mars/mars/operands.py", line 283, in _create_chunk
raise ValueError('output_type should be specified')
ValueError: output_type should be specified

# Fixed code
def spawn(func, args=(), kwargs=None, retry_when_fail=False, n_output=None):
    """
    Spawn a function and return a Mars Object which can be executed later.

    Parameters
    ----------
    func : function
        Function to spawn.
    args: tuple
       Args to pass to function
    kwargs: dict
       Kwargs to pass to function
    retry_when_fail: bool, default False
       If True, retry when function failed.
    n_output: int
       Count of outputs for the function

    Returns
    -------
    Object
        Mars Object.

    Examples
    --------
    >>> import mars.remote as mr
    >>> def inc(x):
    >>>     return x + 1
    >>>
    >>> result = mr.spawn(inc, args=(0,))
    >>> result
    Object <op=RemoteFunction, key=e0b31261d70dd9b1e00da469666d72d9>
    >>> result.execute().fetch()
    1

    List of spawned functions can be converted to :class:`mars.remote.ExecutableTuple`,
    and `.execute()` can be called to run together.

    >>> results = [mr.spawn(inc, args=(i,)) for i in range(10)]
    >>> mr.ExecutableTuple(results).execute().fetch()
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    Mars Object returned by :meth:`mars.remote.spawn` can be treated
    as arguments for other spawn functions.

    >>> results = [mr.spawn(inc, args=(i,)) for i in range(10)]   # list of spawned functions
    >>> def sum_all(xs):
            return sum(xs)
    >>> mr.spawn(sum_all, args=(results,)).execute().fetch()
    55

    inside a spawned function, new functions can be spawned.

    >>> def driver():
    >>>     results = [mr.spawn(inc, args=(i,)) for i in range(10)]
    >>>     return mr.ExecutableTuple(results).execute().fetch()
    >>>
    >>> mr.spawn(driver).execute().fetch()
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    Mars tensor, DataFrame and so forth is available in spawned functions as well.

    >>> import mars.tensor as mt
    >>> def driver2():
    >>>     t = mt.random.rand(10, 10)
    >>>     return t.sum().to_numpy()
    >>>
    >>> mr.spawn(driver2).execute().fetch()
    52.47844223908132

    Argument of `n_output` can indicate that the spawned function will return multiple outputs.
    This is important when some of the outputs may be passed to different functions.

    >>> def triage(alist):
    >>>     ret = [], []
    >>>     for i in alist:
    >>>         if i < 0.5:
    >>>             ret[0].append(i)
    >>>         else:
    >>>             ret[1].append(i)
    >>>     return ret
    >>>
    >>> def sum_all(xs):
    >>>     return sum(xs)
    >>>
    >>> l = [0.4, 0.7, 0.2, 0.8]
    >>> la, lb = mr.spawn(triage, args=(l,), n_output=2)
    >>>
    >>> sa = mr.spawn(sum_all, args=(la,))
    >>> sb = mr.spawn(sum_all, args=(lb,))
    >>> mr.ExecutableTuple([sa, sb]).execute().fetch()
    >>> [0.6000000000000001, 1.5]
    """
    if not isinstance(args, tuple):
        args = [args]
    else:
        args = list(args)
    if kwargs is None:
        kwargs = dict()
    if not isinstance(kwargs, dict):
        raise TypeError("kwargs has to be a dict")

    op = RemoteFunction(
        function=func,
        function_args=args,
        function_kwargs=kwargs,
        retry_when_fail=retry_when_fail,
        n_output=n_output,
    )
    return op()