如何使用 Py4J 在 Python 中实例化 Scala case 对象?
How can I instantiate a Scala case object in Python using Py4J?
我有一个这样定义的 Scala case 对象:
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 实例化该 case 对象的实例的地步,我可以'不知道该怎么做。
我在 https://github.com/awslabs/deequ/issues/109#issuecomment-504220206 找到了一个有用的参考,它教我使用 javap
找到 DurationUnitsOfMeasure
的 class 结构
$ 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', 'module', 'ne', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref', '_build_args', '_gateway_doc', '_get_args', 'command_header', 'container', 'converters', 'gateway_client', 'name', 'pool', 'stream', 'target_id']
但我不知道如何做我想做的事情,即实例化 DurationUnitsOfMeasure.Day
的实例。我试过这个:
jDurationsUnitsOfMeasureDay = getattr(
self.spark._sc._jvm.com.package.DurationUnitsOfMeasure,
"durationUnitsOfMeasure$Day")
但这只是被错误炸毁了:
py4j.protocol.Py4JError: com.package.DurationUnitsOfMeasure.durationUnitsOfMeasure$Day does not exist in the JVM
感觉自己离Python实例化DurationUnitsOfMeasure.Day
已经不远了,但是还没解决。任何建议将不胜感激。
原来我把它复杂化了。这有效:
jDurationUnitsOfMeasure = self.spark._sc._jvm.scala.collection.JavaConversions.seqAsJavaList(
self.spark._sc._jvm.com.package.DurationUnitsOfMeasure.durationUnitsOfMeasure())
那个 returns 一个 py4j.java_collections.JavaList
存在,因此可以将其视为一个好的 ol' Python 列表,因此我可以像处理任何其他列表一样操作它 Python 列表(我更喜欢列表理解)。
我有一个这样定义的 Scala case 对象:
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 实例化该 case 对象的实例的地步,我可以'不知道该怎么做。
我在 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', 'module', 'ne', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref', '_build_args', '_gateway_doc', '_get_args', 'command_header', 'container', 'converters', 'gateway_client', 'name', 'pool', 'stream', 'target_id']
但我不知道如何做我想做的事情,即实例化 DurationUnitsOfMeasure.Day
的实例。我试过这个:
jDurationsUnitsOfMeasureDay = getattr(
self.spark._sc._jvm.com.package.DurationUnitsOfMeasure,
"durationUnitsOfMeasure$Day")
但这只是被错误炸毁了:
py4j.protocol.Py4JError: com.package.DurationUnitsOfMeasure.durationUnitsOfMeasure$Day does not exist in the JVM
感觉自己离Python实例化DurationUnitsOfMeasure.Day
已经不远了,但是还没解决。任何建议将不胜感激。
原来我把它复杂化了。这有效:
jDurationUnitsOfMeasure = self.spark._sc._jvm.scala.collection.JavaConversions.seqAsJavaList(
self.spark._sc._jvm.com.package.DurationUnitsOfMeasure.durationUnitsOfMeasure())
那个 returns 一个 py4j.java_collections.JavaList
存在,因此可以将其视为一个好的 ol' Python 列表,因此我可以像处理任何其他列表一样操作它 Python 列表(我更喜欢列表理解)。