我在EMR的Pyspark看到一个问题,如果我导入了一个叫pyspark.sql.functions.udf()
的鸡蛋,那么Spark处理会挂起。
我正在使用Spark 2.1.0,Zeppelin 0.6.2,Ganglia 3.7.2运行emr-5.3.1的EMR集群。
我希望能够创建一个可以用于各种工作的UDF库。
在我正在运行的Zeppelin笔记本中:
%pyspark
sc.addPyFile("s3://your_s3_path/my_egg-0.1-py2.7.egg")
from my_egg import *
obj = MyClass(sqlContext)
obj.do_map()
my_egg中的代码是:
from pyspark.sql.types import *
def my_scalar_func(input):
return input
from pyspark.sql.functions import udf
# This is the line that causes the whole thing to hang. Uncomment it to reproduce the issue
udf_my_scalar_func = udf(my_scalar_func, StringType())
def my_map_func(row):
return row
class MyClass(object):
def __init__(self, sqlContext):
self.sqlContext = sqlContext
self.raw_data = [{"id": 1, "name": "first"}]
self.schema = StructType([StructField("id", IntegerType(), False), StructField("name", StringType(), False)])
def do_map(self):
print "Creating data frame"
self.df = self.sqlContext.createDataFrame(self.raw_data, self.schema)
print "Data frame: {0}".format(self.df.collect())
self.rdd = self.df.rdd.map(my_map_func)
# The collect() call hangs if the UDF line above is uncommented
print "Mapped RDD: {0}".format(self.rdd.collect())
处理在do_map()
的最后一行(执行rdd.map()和collect()的过程中)挂起。我已经等了3个小时才杀了这份工作。
如果我注释掉定义udf_my_scalar_func
的行,则整个过程会在不到一秒的时间内执行。
请注意,udf_my_scalar_func
和my_scalar_func
永远不会被调用,并且与实际执行的代码没有任何关系。
我对Spark和Pyspark内部的了解不足以弄清楚为什么会这样。怎么解释?有没有办法在一个鸡蛋中定义一个UDF?或者是否有另一种方法可以创建一个UDF库,这些UDF可以轻松访问提交给集群的Pyspark作业?
我创建了一个Github仓库,其中包含一系列完整步骤来重现此问题,包括在https://github.com/ss-emonsen/emr_udf_egg创建EMR群集。