[英]Retrieve a local object from executor/worker in Spark
有没有办法从 Spark 中的工作程序/执行程序中检索局部变量(甚至是全局变量)? 说,我想检索名为 ph_list 的列表并具有以下代码:
from typing import Iterator
import pandas as pd
df = spark.createDataFrame([(1, 21), (2, 30)], ("id", "age"))
def pandas_filter(iterator: Iterator[pd.DataFrame]) -> Iterator[pd.DataFrame]:
ph_list = []
i = 0
for pdf in iterator:
ph_list.append(i)
i += 1
yield pdf[pdf.id == 1]
df.mapInPandas(pandas_filter, schema=df.schema).show()
执行代码后,没有名为 ph_list 的 object 可用。 唯一返回的是 function 应该返回的数据帧,仅此而已。 但是,有时(在这种情况下)我们想要返回无法保存到 spark 数据帧中的东西(如对象),因此出现了问题。
谢谢
DataFrame API 不适用于自定义对象。 DataFrames 的优点是定义了已知类型的模式,这允许 Spark 在内部优化计算。
如果需要灵活性,可以使用RDD API。 它提供对计算返回的对象的完全控制。 然而,Spark 将它们视为黑匣子。
这是一个简单的例子:
df.rdd.map(lambda row: pickle.dumps(row))
PythonRDD[30] at RDD at PythonRDD.scala:53
上面的代码使用 pickle 序列化行并返回一个字节 object。 返回的类型是PythonRDD
,如果你做一个collect
,你会得到一个字节列表,但它可以是任何类型。
df.rdd.map(lambda row: pickle.dumps(row)).map(type).collect()
[<class 'bytes'>, <class 'bytes'>]
编辑:正如评论中所讨论的,您可以通过在 DataFrame 中添加 BinaryType 列并在其中对 model 进行序列化来解决问题。 这是一个例子:
from typing import Iterator
import pandas as pd
import pickle
df = spark.createDataFrame([(1, 21), (2, 30)], ("id", "age"))
def pandas_filter(iterator: Iterator[pd.DataFrame]) -> Iterator[pd.DataFrame]:
ph_list = []
i = 0
for pdf in iterator:
ph_list.append(i)
i += 1
pdf_ph = pdf[pdf.id == 1]
pdf_ph["ph_pkl"] = pickle.dumps(ph_list)
yield pdf_ph
from pyspark.sql.types import LongType, BinaryType
new_schema = StructType([StructField("id", LongType(), True),
StructField("age", LongType(), True),
StructField("ph_pkl", BinaryType(), True)])
df.mapInPandas(pandas_filter, schema=new_schema).show()
结果:
+---+---+----------------------------+
|id |age|ph_pkl |
+---+---+----------------------------+
|1 |21 |[80 03 5D 71 00 4B 00 61 2E]|
+---+---+----------------------------+
该列表可以“收集”和反序列化:
rows = df.mapInPandas(pandas_filter, schema=new_schema).take(1)
pickle.loads(rows[0].ph_pkl)
结果:
[0]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.