我正在尝试编写一个Python实用程序函数,该函数接受PySpark DataFrame withColumn
调用中的本地定义类的对象,并将该类的方法之一用作用户定义函数(UDF)。 。实用程序功能签名为:
def spark_analyze(lp: LogProcessor):
在LogProcessor
类中,我有一个想用作UDF的方法。方法定义为:
schema = StructType([
StructField("total", IntegerType(), False),
StructField("other", IntegerType(), False)
])
def ProcessLog(self, log_file):
self.PrepareForLog()
for event in pyspark_utils.spark_events_from_file(log_file):
self.ProcessEvent(event)
return [total, other]
在spark_analyze
中,我执行以下操作,其中lp
是类型LogProcessor
的传入对象:
@udf(lp.schema)
def lpf(lcm_file):
lp.ProcessLog(lcm_file)
return (df.withColumn('results', lpf(col('logfile_dir')))
...
这会产生一个很长的Python堆栈跟踪,其开始如下:
/home/david/libs.zip/pyspark_utils.py在spark_analyze(lp)中 132 def lpf(lcm_file): 133.lp.ProcessLog(lcm_file) -> 134 return(df.withColumn('results',lpf(col('logfile_dir')))) 135 .withColumn('日志名称',spark_get_dataset_name(col('logfile_dir'))) 136 .select('log name','results。*')
包装中的/usr/hdp/current/spark2-client/python/lib/pyspark.zip/pyspark/sql/functions.py(* args) 1955 @ functools.wraps(f) 1956年def包装器(* args): -> 1957年返回udf_obj(* args) 1958年 1959 wrapper.func = udf_obj.func
结尾为:
/home/david/libs.zip/pyspark_utils.py在spark_analyze(lp)中 132 def lpf(lcm_file): 133.lp.ProcessLog(lcm_file) -> 134 return(df.withColumn('results',lpf(col('logfile_dir')))) 135 .withColumn('日志名称',spark_get_dataset_name(col('logfile_dir'))) 136 .select('log name','results。*')
包装中的/usr/hdp/current/spark2-client/python/lib/pyspark.zip/pyspark/sql/functions.py(* args) 1955 @ functools.wraps(f) 1956年def包装器(* args): -> 1957年返回udf_obj(* args) 1958年 1959 wrapper.func = udf_obj.func
我做了一些测试,发现如果在将UDF传递给col
的位置上方定义UDF,则一切正常。我还尝试将ProcessLog
重新定义为return [0,0]
,发现问题并没有消失。所以问题似乎是我正在使用传入的类对象的方法作为UDF。还有另一种方法可以让UDF成为类中的方法吗?感谢您的帮助!
答案 0 :(得分:0)
Usman Azhar建议的方法可能有效。我最终通过简单地将UDF的定义作为库函数的参数传递来解决了这个问题。