我有一个pyspark流作业,其工作大致如下:
def printrddcount(rdd):
c = rdd.count()
print("{1}: Received an RDD of {0} rows".format("CANNOTCOUNT", datetime.now().isoformat()) )
然后:
...
stream.foreachRDD(printrddcount)
从我得到的结果中,将在worker中执行printrdd函数 而且,是的,我知道在工作程序中执行print()是个坏主意。但这不是重点。 我很确定,直到最近,这段代码才能正常工作。 (而且,它看起来也有所不同,因为'c'的内容实际上是在print语句中打印的,而不是仅仅被收集,然后被丢弃...)
但是现在看来(突然之间?),然后rdd.count()停止工作了,这使我的工作进程死了,说:
UnpicklingError: NEWOBJ class argument has NULL tp_new
完整(仅适用于python)stacktrace:
Caused by: org.apache.spark.api.python.PythonException: Traceback (most recent call last):
File "/usr/hdp/current/spark2-client/python/lib/pyspark.zip/pyspark/worker.py", line 163, in main
func, profiler, deserializer, serializer = read_command(pickleSer, infile)
File "/usr/hdp/current/spark2-client/python/lib/pyspark.zip/pyspark/worker.py", line 54, in read_command
command = serializer._read_with_length(file)
File "/usr/hdp/current/spark2-client/python/lib/pyspark.zip/pyspark/serializers.py", line 169, in _read_with_length
return self.loads(obj)
File "/usr/hdp/current/spark2-client/python/lib/pyspark.zip/pyspark/serializers.py", line 454, in loads
return pickle.loads(obj)
UnpicklingError: NEWOBJ class argument has NULL tp_new
失败的那一行确实是rdd.count()
有人知道rdd.count()为什么会失败吗? 如果应该序列化某些内容,则应该是rdd,对吧?
答案 0 :(得分:0)
好的。我进一步调查了。 rdd.count()没问题
唯一的错误是,rdd在管道上存在另一种以某种方式“损坏”(关闭?无效?沿着这些方向的东西)的转换。 因此,当使用printrddcount函数时,它无法再进行序列化并给出错误。
问题出在如下代码中:
...
log = logging.getLogger(__name__)
...
def parse(parse_function):
def parse_function_wrapper(event):
try:
log.info("parsing")
new_event = parse_function(event)
except ParsingFailedException as e:
pass
return new_event
return parse_function_wrapper
然后:
stream = stream.map(parse(parse_event))
现在,log.info(尝试了很多变体,开始时是在异常处理程序中进行记录)才是造成问题的原因。 这使我说,很可能是由于某种原因而无法序列化的记录器对象。
我自己关闭了该线程,因为它实际上与rdd序列化无关;甚至甚至没有使用pyspark。