我在Hadoop中有一个自定义可写类,它保存为序列文件,如下所示
public class ABC implements Writable{
private byte[] myId;
private byte[] myType;
//Constructor and other methods
@Override
public void write(DataOutput out) throws IOException {
myId.write(out);
myType.write(out);
}
@Override
public void readFields(DataInput in) throws IOException {
myId.readFields(in);
myType.readFields(in);
}
}
我想使用PySpark读取序列文件并获取数据。我尝试了以下三种方式:
sc.sequenceFile(" file:///Test.seq" ;, keyClass =" ABC",valueClass =" ABC")
但是
object not serializable (class: ABC, value: ABC@451de3ec)
来自官方教程http://spark.apache.org/docs/latest/programming-guide.html#external-datasets,其中说
如果您有自定义序列化二进制数据(例如从中加载数据) Cassandra / HBase),那么你首先需要转换那些数据 Scala / Java方面可以用Pyrolite来处理 皮克勒。为此提供了转换器特性。简单地扩展一下 trait并在convert方法中实现转换代码。
因此,我按如下方式实现转换器:
import test.ABC
import java.io.DataInput
import org.apache.spark.api.python.Converter
/**
* Implementation of [[org.apache.spark.api.python.Converter]] that converts data
* to ABC
*/
class DataToABCConverter extends Converter[Any, ABC] {
override def convert(obj: Any): ABC = {
if (obj == null) {
return null
}
val in = obj.asInstanceOf[DataInput]
val abc = new ABC()
abc.readFields(in)
abc
}
}
在PySpark中,我使用以下代码
sc.sequenceFile("file:///Test.seq", keyClass = "ABC", valueClass ="ABC", keyConverter="DataToABCConverter", valueConverter="DataToABCConverter" )
但是得到以下错误
java.lang.ClassCastException: ABC cannot be cast to java.io.DataInput
转换器的输入似乎是我的ABC类而不是java.io.DataInput,因此我无法应用readFields方法来获取数据。
我添加geID()
方法来获取byets并按如下方式更改转换器:
class DataToChunkConverter extends Converter[Any, BytesWritable] {
override def convert(obj: Any): BytesWritable = {
if (obj == null) {
return null
}
val abc = obj.asInstanceOf[ABC]
val idd = abc.getID()
new BytesWritable(idd)
}
}
比我使用
运行pysparkpyspark --master=local[8] --conf "spark.kryo.classesToRegister=org.apache.hadoop.io.BytesWritable" --conf "spark.serializer=org.apache.spark.serializer.KryoSerializer"
但是得到以下错误
Failed to pickle Java object as value: BytesWritable, falling back
to 'toString'. Error: couldn't pickle object of type class org.apache.hadoop.io.BytesWritable
所以我的问题是在PySpark中读取自定义序列文件的正确方法是什么?什么类型可以通过PySpark序列化?任何建议表示赞赏!!
答案 0 :(得分:0)
经过一些实验(遵循第三种方法),事实证明,如果将scala或Java中的本机类型用作转换器的返回类型,它就可以工作。
例如,使用Array[Byte]
作为返回类型,Pyspark可以成功获取数据:
class DataToChunkConverter extends Converter[Any, Array[Byte]] {
override def convert(obj: Any): Array[Byte] = {
if (obj == null) {
return null
}
val abc = obj.asInstanceOf[ABC]
val idd = abc.getID()
idd
}
}