繁体   English   中英

从 Spark 中的 executor/worker 检索本地 object

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM