简体   繁体   中英

Using itertools.groupby in pyspark but fail

I wrote a map function to aggregate data by using itertools.groupby, and what I do is like below.

Driver code

pair_count = df.mapPartitions(lambda iterable: pair_func_cnt(iterable))
pair_count.collection()

Map function

def pair_func_cnt(iterable):
    from itertools import groupby

    ls = [[1,2,3],[1,2,5],[1,3,5],[2,4,6]]
    grp1 = [(k,g) for k,g in groupby(ls, lambda e: e[0])]
    grp2 = [(k,g) for k,g in groupby(grp1, lambda e: e[1])]
    return iter(grp2)

But it gives the following error

Caused by: org.apache.spark.api.python.PythonException: Traceback (most recent call last):
  File "/opt/zeppelin-0.6.0-bin-netinst/interpreter/spark/pyspark/pyspark.zip/pyspark/worker.py", line 111, in main
    process()
  File "/opt/zeppelin-0.6.0-bin-netinst/interpreter/spark/pyspark/pyspark.zip/pyspark/worker.py", line 106, in process
    serializer.dump_stream(func(split_index, iterator), outfile)
  File "/opt/zeppelin-0.6.0-bin-netinst/interpreter/spark/pyspark/pyspark.zip/pyspark/serializers.py", line 267, in dump_stream
    bytes = self.serializer.dumps(vs)
  File "/opt/zeppelin-0.6.0-bin-netinst/interpreter/spark/pyspark/pyspark.zip/pyspark/serializers.py", line 415, in dumps
    return pickle.dumps(obj, protocol)
PicklingError: Can't pickle <type 'itertools._grouper'>: attribute lookup itertools._grouper failed
    at org.apache.spark.api.python.PythonRunner$$anon$1.read(PythonRDD.scala:166)
    at org.apache.spark.api.python.PythonRunner$$anon$1.<init>(PythonRDD.scala:207)
    at org.apache.spark.api.python.PythonRunner.compute(PythonRDD.scala:125)
    at org.apache.spark.api.python.PythonRDD.compute(PythonRDD.scala:70)
    at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:306)
    at org.apache.spark.rdd.RDD.iterator(RDD.scala:270)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
    at org.apache.spark.scheduler.Task.run(Task.scala:89)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:214)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    ... 1 more

Python pickle cannot serialize anonymous functions. Lets illustrate that on a simplified example:

import pickle

xs = [[1, 2, 3], [1, 2, 5], [1, 3, 5], [2, 4, 6]]
pickle.dumps([x for x in  groupby(xs, lambda x: x[0])])

## PicklingError
## ...
## PicklingError: Can't pickle ...

You should get rid of all references to the lambdas before serializing:

pickle.dumps([(k, list(v)) for (k, v) in groupby(xs, itemgetter(0))])

## b'\x80\x ...

or don't use lambda expressions:

from operator import itemgetter

pickle.dumps([kv for kv in groupby(xs, itemgetter(0))])

## b'\x80\x ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM