Невозможно запустить сценарий python из java jar - PullRequest
0 голосов
/ 27 мая 2020

При работе в IntelliJ все работало, но после того, как я построил jar, он остановился. Сначала я просто забыл поместить его в конфигурацию сборки jar, но теперь, убедившись, что он там, я все еще не могу его запустить. Вот способы, которые я пробую:

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"));

Ни одна тема не работает, несмотря на то, что она есть в ресурсах. Я также попытался указать путь к нему в проекте IntelliJ, и он работает, но только при запуске из IntelliJ после того, как я запускаю его из jar, это не так.

Edit1: для людей, которые не понимали файл py jar файл

1 Ответ

1 голос
/ 27 мая 2020

Ни один из вариантов, в которых вы пытаетесь выполнить "python3 "+script и эквиваленты, не будет работать. script - это InputStream, а не путь в файловой системе, поэтому простое объединение его с String не даст вам ничего значимого. Кроме того, поскольку ваш скрипт находится не в собственном файле, и интерпретатор python не может извлечь его просто, просто вызвать его в таком виде не получится.

Однако что вы можете сделать, это выполнить

python3 -

Опция - здесь (по крайней мере, в BSD-подобных системах) означает «читать со стандартного ввода и интерпретировать его как сценарий». Затем на стороне Java вы можете прочитать ресурс, упакованный в jar, как поток и направить его на стандартный ввод процесса python.

Подробнее о выборе правильного пути для ресурса см. Как определить правильный путь для файлов F XML, CSS файлов, изображений и других ресурсов, необходимых моему приложению JavaFX? .

Следующее, в котором скрипт просто помещается в тот же пакет, что и класс, у меня работает:

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:

enter image description here

Содержимое 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
$
...