无法从 java jar 中 运行 python 脚本

Cannot run python script from java jar

在 IntelliJ 中工作时一切正常,但在我构建 jar 后它停止了。起初只是我忘记把它放在 jar build config 中,但现在确定它在那里后,我仍然不能 运行 它。这些是我尝试的方法:

InputStream script = mainView.class.getResourceAsStream("vizualize3D.py");
Process process = new ProcessBuilder("python3", "-").start() ;

Process p1 = Runtime.getRuntime().exec("python3 " + script);

Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("python3 " + mainView.class.getResourceAsStream("vizualize3D.py"));

None 的主题作品,尽管它在资源中。我还尝试在 IntelliJ 项目中指定它的路径并且它有效,但只有当我从 jar 启动它后来自 IntelliJ 的 运行 它才不起作用。

编辑1: 对于不理解 py 文件在 jar 文件中的人

None 涉及您尝试执行 "python3 "+script 的选项和等效项将起作用。 script 是一个 InputStream,不是文件系统上的路径,所以简单地将它与 String 连接起来不会给你任何有意义的东西。此外,由于您的脚本不在其自己的文件中,并且 python 解释器没有简单的方法来提取它,因此像这样简单地调用它是行不通的。

但是,您可以执行

python3 -

此处的 - 选项(至少在类 BSD 系统上)表示 "read from standard input, and interpret it as a script"。然后,在 Java 端,您可以将 jar 打包的资源作为流读取并将其通过管道传输到 python 进程的标准输入。

有关为资源选择正确路径的详细信息,请参阅

下面的脚本与 class 放在同一个包中,对我有用:

PythonRunner.java:

package example.python;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

public class PythonRunner {

    public static void main(String[] args) throws Exception {

        String pythonInterpreter = "/usr/bin/python3" ; // default
        if (args.length > 0) {
            pythonInterpreter = args[0] ;
        }

        InputStream script = PythonRunner.class.getResourceAsStream("script.py");
        Process pythonProcess = new ProcessBuilder(pythonInterpreter, "-")
                .start();

        // This thread reads the output from the process and 
        // processes it (in this case just dumps it to standard out)
        new Thread(() ->  {
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(pythonProcess.getInputStream()))) {

                for (String line ; (line = reader.readLine()) != null ;) {
                    System.out.println(line);
                }
            } catch (IOException exc) {
                exc.printStackTrace();
            }
        }).start();

        // read the script from the resource, and pipe it to the
        // python process's standard input (which will be read because
        // of the '-' option)
        OutputStream stdin = pythonProcess.getOutputStream();
        byte[] buffer = new byte[1024];
        for (int read = 0 ; read >= 0 ; read = script.read(buffer)) {
            stdin.write(buffer, 0, read);
        }
        stdin.close();
    }

}

script.py:

import sys

for i in range(10):
    print("Spam")

sys.exit(0)

MANIFEST.MF

Manifest-Version: 1.0
Main-Class: example.python.PythonRunner

Eclipse 布局:

Jar 内容和 运行 的结果:

$ jar tf runPython.jar 
META-INF/MANIFEST.MF
example/python/PythonRunner.class
example/python/script.py
$ java -jar runPython.jar 
Spam
Spam
Spam
Spam
Spam
Spam
Spam
Spam
Spam
Spam
$