Spark-Submit" _pickle.PicklingError:来自__newobj__ args的args [0]错误的类"

时间:2017-10-22 19:18:46

标签: python pyspark pickle user-defined-functions apache-zeppelin

尝试通过Spark-Submit或Zeppelin运行一些代码时出现以下错误:" _pickle.PicklingError:__ newobj __ args中的args [0]错误的类"

我已经查看了同样问题的帖子,对这个问题有很多了解。

回溯(包含在下面)指向我使用的其中一个udf:

udf_stop_words = udf(stop_words, ArrayType(StringType()))

def stop_words(words):
    return list(word.lower() for word in words if word.lower() not in  stopwords.words("english"))

函数的输入和输出都是字符串列表。这些是来自输入的3行:

  

[Row(split_tokenized_activity_description = [' A','令人愉快的',' 45',   '分钟'瑞典','风格','按摩']),   行(split_tokenized_activity_description = [' A','更多','激烈',   ' 45''分钟','版本','',' a','瑞典& #39;,' style',' massage']),   行(split_tokenized_activity_description = [' A','放松',' 45',   '分钟'瑞典','风格','按摩'])

这是我正在使用的代码片段。

def special_car(x):
    # remove the special character and replace them with the stop word " " (space)
    return [re.sub('[^A-Za-z0-9]+', ' ', x)]

# Create UDF from function
udf_special_car = udf(special_car, ArrayType(StringType()))

# Function to remove stops words
def stop_words(words):
    return list(word.lower() for word in words if word.lower() not in  stopwords.words("english"))

udf_stop_words = udf(stop_words, ArrayType(StringType()))

# Load in data
df_tags = spark.sql("select * from database")

# Remove special Characters
df1_tags = df_tags.withColumn('tokenized_name', udf_special_car(df_tags.name))
df2_tags = df1_tags.withColumn('tokenized_description', udf_special_car(df1_tags.description))

# Select only relevent columns
df3_tags = df2_tags.select(['tag_id', 'tokenized_name', 'tokenized_description'])

# Tokenize tag_name and tag_desc (Seperate on spaces) (This uses the pyspark.sql.split function)
df4_tags = df3_tags.withColumn('split_tokenized_name', split(df3_tags['tokenized_name'].getItem(0), ' '))
df5_tags = df4_tags.withColumn('split_tokenized_description', split(df3_tags['tokenized_description'].getItem(0), ' '))

# Select only relevent columns
df6_tags = df5_tags.select(['tag_id', 'split_tokenized_name', 'split_tokenized_description'])

# Remove Stop words
df7_tags = df6_tags.withColumn('stop_words_tokenized_name', udf_stop_words(df6_tags.split_tokenized_name))
df8_tags = df7_tags.withColumn('stop_words_tokenized_description', udf_stop_words(df7_tags.split_tokenized_description))

奇怪的是,通过Zeppelin运行我的代码的前两个时间我得到了错误,但是在第3次尝试之后,它运行得很好,输出就是我期望的结果。但Zeppelin仅用于测试;我需要让它通过Spark-Submit运行。

  

Traceback(最近一次调用最后一次):文件   " /tmp/testing_test.py" ;,第262行,in       udf_stop_words = udf(stop_words,ArrayType(StringType()))文件" /usr/lib/spark/python/lib/pyspark.zip/pyspark/sql/functions.py" ;, line   1872年,在udf文件中   " /usr/lib/spark/python/lib/pyspark.zip/pyspark/sql/functions.py" ;, line   1830年,在 init 文件中   " /usr/lib/spark/python/lib/pyspark.zip/pyspark/sql/functions.py" ;, line   1835年,在_create_judf文件中   " /usr/lib/spark/python/lib/pyspark.zip/pyspark/sql/functions.py" ;, line   1815年,在_wrap_function文件中   " /usr/lib/spark/python/lib/pyspark.zip/pyspark/rdd.py" ;,第2359行,在   _prepare_for_python_RDD文件" /usr/lib/spark/python/lib/pyspark.zip/pyspark/serializers.py" ;, line   460,在转储文件中   " /usr/lib/spark/python/lib/pyspark.zip/pyspark/cloudpickle.py" ;, line   703,在转储文件中   " /usr/lib/spark/python/lib/pyspark.zip/pyspark/cloudpickle.py" ;, line   147,在转储文件" /home/hadoop/anaconda/lib/python3.6/pickle.py"中,   409行,在转储中       self.save(obj)File" /home/hadoop/anaconda/lib/python3.6/pickle.py" ;,第476行,保存       f(self,obj)#使用显式自我文件" /home/hadoop/anaconda/lib/python3.6/pickle.py" ;,第736行调用未绑定方法   save_tuple       保存(元素)文件" /home/hadoop/anaconda/lib/python3.6/pickle.py" ;,第476行,保存       f(self,obj)#使用显式自我文件调用未绑定方法" /usr/lib/spark/python/lib/pyspark.zip/pyspark/cloudpickle.py" ;, line   248,在save_function文件中   " /usr/lib/spark/python/lib/pyspark.zip/pyspark/cloudpickle.py" ;, line   296,在save_function_tuple文件中   " /home/hadoop/anaconda/lib/python3.6/pickle.py" ;,第476行,保存       f(self,obj)#使用显式自我文件" /home/hadoop/anaconda/lib/python3.6/pickle.py" ;,第821行调用未绑定方法   save_dict       self._batch_setitems(obj.items())File" /home/hadoop/anaconda/lib/python3.6/pickle.py" ;,第852行,在   _batch_setitems       保存(v)文件" /home/hadoop/anaconda/lib/python3.6/pickle.py" ;,第521行,保存       self.save_reduce(obj = obj,* rv)File" /usr/lib/spark/python/lib/pyspark.zip/pyspark/cloudpickle.py" ;, line   564,在save_reduce中   _pickle.PicklingError:来自 newobj args的args [0]有错误的类

我已经尝试了几个方法来解决这个问题,但没有一个能够解决这个问题。它们都返回相同的错误。

我尝试将udf更改为单行lambda函数:

udf(lambda words: list(word.lower() for word in words if word.lower() not in stopwords.words('english')), ArrayType(StringType())).

我尝试更改udf以返回字符串:

udf_stop_words = udf(stop_words, StringType())

并将udf更改为匹配。

def stop_words(words):
    return str(word.lower() for word in words if word.lower() not in stopwords.words('english'))

我试图将它定义为具有以下两者的StructType:

udf_stop_words = udf(stop_words, StructType([StructField("words", ArrayType(StringType()), False)])) 

udf_stop_words = udf(stop_words, StructType([StructField("words", StringType(), False)])).

我也尝试了上述的许多组合。

2 个答案:

答案 0 :(得分:0)

返回类型应为function git_merge_squash() { git merge --squash "$1" shift git commit -m "$(echo $'\n'"$*" | tr . \\n | tr - ' ')" } alias gmrs=git_merge_squash

我不确定这一点,但问题可能来自您未在节点上安装ArrayType(StringType())的事实(或者nltk corpus从未在节点上下载)。由于在stopwords内调用stopwords.words("english")就像在节点上调用它一样,因此它可能会失败,因为它无法找到语料库。

由于UDF只是一个列表,您应该在驱动程序上调用它,然后将其广播到节点:

stopwords.words("english")

答案 1 :(得分:0)

我有类似的问题。在我的情况下,异常被抛出,因为我在我的spark脚本本身中定义了一个类。它是通过创建包含类定义和方法的单独.py文件来解决的。然后通过sc.addPyFile(path)并最后from FileName import *将该脚本添加到您的脚本中。