【问题标题】:Unable to launch gateway from Python in py4j无法在 py4j 中从 Python 启动网关
【发布时间】:2018-07-14 01:07:53
【问题描述】:

我正在尝试使用 py4j 从 Python 端启动 JavaGateway。以下是重现我遇到的问题所需的最少文件。

py4j.Py4JException:此网关的目标对象 ID 不存在:t

A.java

public class A {
}

EntryPoint.java

import py4j.GatewayServer;

public class EntryPoint {
    public A getA() {
        return new A();
    }

    public static void main(String[] args) {
        GatewayServer gatewayServer = new GatewayServer(new EntryPoint());
        gatewayServer.start();
        System.out.println("server started");
    }
}

我使用 IntelliJ 构建 .jar 文件,其中主类为 EntryPointpy4j.jar 作为依赖项包含在内。

现在,我尝试通过在 python 中引用生成的.jar 文件的路径来启动网关。

test.py

from py4j.java_gateway import JavaGateway

gateway = JavaGateway.launch_gateway(classpath = '../out/artifacts/debugPy4j_jar/debugPy4j.jar')

a = gateway.entry_point.getA()

任何有关解决此问题的建议将不胜感激。

【问题讨论】:

    标签: java python py4j


    【解决方案1】:

    您无法使用 launch_gateway 指定自定义 Main 类,这意味着您无法指定入口点。您只能指定一个类路径,该路径附加到 Py4J jar 文件的路径中。

    “t”是Java端入口点的名称:因为没有入口点,Py4J找不到对象“t”。可以说,此实现细节不应在面向用户的异常中泄露。

    launch_gateway 被硬编码为使用 py4j.GatewayServer 作为主类,因为它期望 Java 端以某种方式运行。

    在您的情况下,您仍然可以在 GatewayServer 启动后从 Python 创建一个 EntryPoint 实例:

    from py4j.java_gateway import JavaGateway
    
    gateway = JavaGateway.launch_gateway(classpath='../out/artifacts/debugPy4j_jar/debugPy4j.jar')
    
    a = gateway.jvm.A()
    

    【讨论】:

    • 你介意举个例子吗?我对py4j不太熟悉
    • 我加了一个例子
    • 如果我错了,请纠正我,但这不会启动网关服务器本身,对吗?它仍然如何工作?
    • 另外,这是否意味着EntryPoint.java 是不必要的?我不能用A.java 构建一个工件并将其用作我的类路径吗?
    • launch_gateway 启动 JVM 和 GatewayServer。 EntryPoint.java 是不必要的。