且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

无法从Java Jar运行python脚本

更新时间:2023-10-21 16:24:10

涉及您尝试执行"python3 "+script的选项和等效选项均无效. scriptInputStream,而不是文件系统上的路径,因此仅将其与String串联将不会给您带来任何有意义的意义.另外,由于您的脚本不在自己的文件中,并且python解释器没有简单的方法来提取它,因此像这样简单地调用它是行不通的.

None of the options involving you trying to execute "python3 "+script, and equivalents, will work. script is an InputStream, not a path on the file system, so simply concatenating it with a String will not give you anything meaningful. Additionally, since your script is not in its own file, and there's no simple way for the python interpreter to extract it, simply invoking it like this won't work.

但是,您可以执行

python3 -

此处的-选项(至少在类似BSD的系统上)表示从标准输入读取并将其解释为脚本".然后,在Java端,您可以将jar打包的资源作为流读取,并通过管道传递到python进程的标准输入.

The - option here (at least on BSD-like systems) means "read from standard input, and interpret it as a script". Then, on the Java side, you can read the jar-packaged resource as a stream and pipe it to the python process's standard input.

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

For details on choosing the correct path for the resource, see How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application?.

下面的代码对我有用:

PythonRunner.java:

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:

script.py:

import sys

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

sys.exit(0)

MANIFEST.MF

MANIFEST.MF

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

Eclipse布局:

Eclipse layout:

大量内容和运行结果:

$ 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
$