如何使用 Py4J 在 Python 中实例化 Scala 案例对象?



我有一个 Scala 案例对象定义如下:

object DurationUnitsOfMeasure {
sealed abstract class DurationUnitOfMeasure(val name : String)
{
override def toString : String = name
lazy val initial: Char = name.charAt(2).toLower
}
case object Day extends DurationUnitOfMeasure("__DAY__")
case object Week extends DurationUnitOfMeasure("__WEEK__")
case object Month extends DurationUnitOfMeasure("__MONTH__")
val durationUnitsOfMeasure : Seq[DurationUnitOfMeasure] = Seq(Day, Week, Month)
}

我正在编写的一些代码使用它来与Spark进行交互。我还想与 Python 中的代码进行交互,我已经使用 Py4J 成功完成了这些代码,但是我现在想要从 Python/PySpark 实例化该案例对象的实例,但我不知道该怎么做。

我在 https://github.com/awslabs/deequ/issues/109#issuecomment-504220206 找到了一个有用的参考,它教我使用javap来查找DurationUnitsOfMeasure的类结构

$ javap -classpath ../target/scala-2.11/foo_2.11-0.1-SNAPSHOT.jar com/package/DurationUnitsOfMeasure
Compiled from "File.scala"
public final class com.package.DurationUnitsOfMeasure {
public static scala.collection.Seq<com.package.DurationUnitsOfMeasure$DurationUnitOfMeasure> durationUnitsOfMeasure();
}

这反过来又导致我编写了这个 Python 代码:

# self.spark is an instance of SparkSession
jDurationsUnitsOfMeasure = getattr(
self.spark._sc._jvm.com.package.DurationUnitsOfMeasure,
"durationUnitsOfMeasure")

jDurationsUnitsOfMeasure是一个<py4j.java_gateway.JavaMember object at 0x7fc0dbb14850,我可以使用通常的python方法进行询问,例如dir()

(Pdb( dir(jDurationsUnitsOfMeasure(['call', 'class', '
delattr', 'dict', 'dir', 'doc', 'eq', 'format', 'ge', 'getattribute', 'gt', 'hash', 'init', 'init_subclass', 'le', 'lt', '模块', 'ne', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref

', '_build_args', '_gateway_doc', '_get_args', 'command_header', '容器', '转换器', 'gateway_client', '名称', '池', '流', 'target_id']

但是我不知道如何做我想做的事情,即实例化DurationUnitsOfMeasure.Day的实例。我试过这个:

jDurationsUnitsOfMeasureDay = getattr(
self.spark._sc._jvm.com.package.DurationUnitsOfMeasure,
"durationUnitsOfMeasure$Day")

但这只是错误地爆炸了:

py4j.protocol.Py4JError: com.package.DurationUnitsOfMeasure.durationUnitsOfMeasure$Day 在 JVM 中不存在

我觉得我离能够从 Python 实例化DurationUnitsOfMeasure.Day不远了,但我还没有解决它。任何建议将不胜感激。

事实证明,我把它复杂化了。这有效:

jDurationUnitsOfMeasure = self.spark._sc._jvm.scala.collection.JavaConversions.seqAsJavaList(
self.spark._sc._jvm.com.package.DurationUnitsOfMeasure.durationUnitsOfMeasure())

这将返回一个存在的py4j.java_collections.JavaList,以便可以将其视为一个好的 ol' Python 列表,因此我可以像处理任何其他 Python 列表一样操作它(我更喜欢列表推导(。

最新更新