如何使用PySpark转换结构化流?

时间:2018-07-25 17:56:35

标签: apache-spark pyspark spark-structured-streaming

这看起来应该很明显,但是在查看文档和示例时,我不确定是否可以找到一种方法来获取结构化流并使用PySpark进行转换。

例如:

from pyspark.sql import SparkSession

spark = (
    SparkSession
    .builder
    .appName('StreamingWordCount')
    .getOrCreate()
)

raw_records = (
    spark
    .readStream
    .format('socket')
    .option('host', 'localhost')
    .option('port', 9999)
    .load()
)

# I realize there's a SQL function for upper-case, just illustrating a sample
# use of an arbitrary map function
records = raw_records.rdd.map(lambda w: w.upper()).toDF()

counts = (
    records
    .groupBy(records.value)
    .count()
)

query = (
    counts
    .writeStream
    .outputMode('complete')
    .format('console')
    .start()
)
query.awaitTermination()

这将引发以下异常:

Queries with streaming sources must be executed with writeStream.start

但是,如果我取消对rdd.map(...).toDF()的呼叫,一切似乎就可以正常工作。

好像对rdd.map的调用从流上下文中分支了执行,并导致Spark警告它从未启动?

是否存在使用“结构化流媒体”和PySpark应用mapmapPartition样式转换的“正确”方法?

2 个答案:

答案 0 :(得分:4)

结构化流中应用的每个转换都必须完全包含在Dataset的世界中-对于PySpark,这意味着您只能使用DataFrame或SQL并转换为RDD(或DStream或本地集合)。

如果要使用纯Python代码,则必须使用UserDefinedFunction

from pyspark.sql.functions import udf

@udf
def to_upper(s)
    return s.upper()

raw_records.select(to_upper("value"))

另请参阅Spark Structured Streaming and Spark-Ml Regression

答案 1 :(得分:0)

用于特定列(column_name)的另一种方法:

from pyspark.sql.functions import udf
from pyspark.sql.types import StringType

def to_uper(string):
    return string.upper()

to_upper_udf = udf(to_upper,StringType())

records = raw_records.withColumn("new_column_name"
                      ,to_upper_udf(raw_records['column_name']))\
                      .drop("column_name")