我编写了以下MyPythonGateway.java,以便我可以从Python调用我的自定义java类:
public class MyPythonGateway {
public String findMyNum(String input) {
return MyUtiltity.parse(input).getMyNum();
}
public static void main(String[] args) {
GatewayServer server = new GatewayServer(new MyPythonGateway());
server.start();
}
}
以下是我在Python代码中使用它的方法:
def main():
gateway = JavaGateway() # connect to the JVM
myObj = gateway.entry_point.findMyNum("1234 GOOD DAY")
print(myObj)
if __name__ == '__main__':
main()
现在我想使用PySpark中的MyPythonGateway.findMyNum()
函数,而不仅仅是一个独立的python脚本。我做了以下事情:
myNum = sparkcontext._jvm.myPackage.MyPythonGateway.findMyNum("1234 GOOD DAY")
print(myNum)
但是,我收到以下错误:
... line 43, in main:
myNum = sparkcontext._jvm.myPackage.MyPythonGateway.findMyNum("1234 GOOD DAY")
File "/home/edamameQ/spark-1.5.2/python/lib/py4j-0.8.2.1-src.zip/py4j/java_gateway.py", line 726, in __getattr__
py4j.protocol.Py4JError: Trying to call a package.
那我在这里想念的是什么?我不知道在使用pyspark时是否应该运行MyPythonGateway的单独JavaApplication来启动网关服务器。请指教。谢谢!
以下是我的需要:
input.map(f)
def f(row):
// call MyUtility.java
// x = MyUtility.parse(row).getMyNum()
// return x
最好的方法是什么?谢谢!
答案 0 :(得分:3)
首先,您看到的错误通常意味着您尝试使用的课程无法访问。所以很可能是CLASSPATH
问题。
关于一般概念,有两个重要问题:
SparkContext
,因此使用PySpark网关无法正常工作(有关详细信息,请参阅How to use Java/Scala function from an action or a transformation?))。如果你想使用工人的Py4J,你必须在每台工人机器上启动一个单独的网关。答案 1 :(得分:0)
在PySpark中开始调用方法之前-
myNum = sparkcontext._jvm.myPackage.MyPythonGateway.findMyNum("1234 GOOD DAY")
您必须按如下所示导入MyPythonGateway java类
java_import(sparkContext._jvm, "myPackage.MyPythonGateway")
myPythonGateway = spark.sparkContext._jvm.MyPythonGateway()
myPythonGateway.findMyNum("1234 GOOD DAY")
使用 spark-submit
中的-jars 选项指定包含myPackage.MyPythonGateway的jar。答案 2 :(得分:0)
例如,如果input.map(f)
具有作为RDD的输入,则此方法可能会起作用,因为您无法为RDD的map函数(以及我的我)访问执行器中的JVM变量(附加到spark上下文)知识在pyspark中没有@transient lazy val
的等效项。
def pythonGatewayIterator(iterator):
results = []
jvm = py4j.java_gateway.JavaGateway().jvm
mygw = jvm.myPackage.MyPythonGateway()
for value in iterator:
results.append(mygw.findMyNum(value))
return results
inputs.mapPartitions(pythonGatewayIterator)
答案 3 :(得分:0)
您需要做的就是编译jar并使用--jars或--driver-class-path spark提交选项将其添加到pyspark classpath中。然后使用以下代码访问类和方法-
sc._jvm.com.company.MyClass.func1()
其中sc-火花上下文
已通过Spark 2.3测试。请记住,您只能从驱动程序而不是执行程序调用JVM类方法。