Py4J序列化:AttributeError:'dict'对象没有属性'_get_object_id'

时间:2019-08-14 22:47:33

标签: python apache-spark serialization pyspark py4j

使用Py4J,我无法将Python字典对象解析为底层JVM实例。

我写了一个PySpark代码,在RDD上运行UDF / lambda函数。我的目标是在RDD的每一行上运行一段Python代码,该代码需要每个执行者内核连接到底层JVM,以便从我自己的自定义jar(源代码在Scala中)中获取Java类实例。在Spark提交期间使用--jars函数进行部署。我尝试了下面的示例,但遇到了提到的错误。该代码在具有Cloudera分布的Spark 2.3集群中的每个执行程序核心上运行。出于安全原因,对代码进行了一些掩盖。

from py4j.java_gateway import JavaGateway, launch_gateway
gateway = JavaGateway().launch_gateway(classpath='custom-code.jar:scala-library-2.11.8.jar:spark-catalyst_2.11-2.3.0.cloudera3.jar:scala-reflect-2.11.8.jar', jarpath='<path-to-py4j-jar>/py4j-0.10.7.jar')
jvm = gateway.jvm
input_dict = {0: 123}
temp = jvm.com.my.code.PyUtil.fullMap(input_dict)

  File "/opt/cloudera/parcels/SPARK2-2.3.0.cloudera3-1.cdh5.13.3.p0.458809/lib/spark2/python/lib/py4j-0.10.7-src.zip/py4j/java_gateway.py", line 1248, in __call__
    args_command, temp_args = self._build_args(*args)
  File "/opt/cloudera/parcels/SPARK2-2.3.0.cloudera3-1.cdh5.13.3.p0.458809/lib/spark2/python/lib/py4j-0.10.7-src.zip/py4j/java_gateway.py", line 1218, in _build_args
    [get_command_part(arg, self.pool) for arg in new_args])
  File "/opt/cloudera/parcels/SPARK2-2.3.0.cloudera3-1.cdh5.13.3.p0.458809/lib/spark2/python/lib/py4j-0.10.7-src.zip/py4j/java_gateway.py", line 1218, in <listcomp>
    [get_command_part(arg, self.pool) for arg in new_args])
  File "/opt/cloudera/parcels/SPARK2-2.3.0.cloudera3-1.cdh5.13.3.p0.458809/lib/spark2/python/lib/py4j-0.10.7-src.zip/py4j/protocol.py", line 298, in get_command_part
    command_part = REFERENCE_TYPE + parameter._get_object_id()
AttributeError: 'dict' object has no attribute '_get_object_id'

奇怪的是,当我运行完全相同的代码,但是调用自定义jar的不同函数时,它接受了String而不是dict,它运行得非常好,并且我得到了py4j.java_gateway.JavaObject,这就是我打算去这里。

看看py4j的发行说明,我知道从0.5版本开始支持字典,所以我不确定在这里我到底在做什么错?我怀疑网关启动有问题。

任何方向性的帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

找到答案,在这里列出:

https://www.py4j.org/advanced_topics.html#converting-python-collections-to-java-collections

我只需要自己手动转换即可。

from py4j.java_collections import MapConverter
input_dict = {0: 123}
mc_run_map_dict = MapConverter().convert(input_dict, gateway_handle._gateway_client)
temp = jvm.com.my.code.PyUtil.fullMap(mc_run_map_dict)