Я пытаюсь запустить скрипт python из моей программы Java. Скрипт python прослушивает соединения сокетов из программы Java и отвечает данными. Для этого я попытался использовать API ProcessBuilder, чтобы:
public class MLClassifierProcess{
//bash location //activate python venv //python interpreter //script
final String[] command_to_run = new String[] { "/bin/bash", "-c", "/env/bin/activate;", "/env/bin/python","predictprobability.py;" };
public void startML(){
ProcessBuilder builder = new ProcessBuilder(command_to_run);
Process pr = null;
try {
pr = builder.start();
} catch (IOException ioException) {
System.out.println("error");
}
}
public static void main(String[] args){
MLClassifierProcess p = new MLClassifierProcess();
p.startML();
}
}
однако выполнение основной функции сразу же прекращается, когда скрипт predprobability.py должен продолжать работать бесконечно. Я новичок в API ProcessBuilder, поэтому любые указания о том, как действовать, были бы очень признательны.




Если ваша программа Java завершается, запускаемый вами процесс Python будет завершен, а дочерние процессы будут уничтожены, когда родительский процесс умирает, если они не были отсоединены от этого процесса.
Если вы хотите, чтобы ваша программа Java продолжала работать до тех пор, пока программа Python не завершит выполнение, вам необходимо, чтобы код Java ожидал надлежащим образом. Вот как это сделать:
public class MLClassifierProcess{
//bash location //activate python venv //python interpreter //script
final String[] command_to_run = new String[] { "/bin/bash", "-c", "/env/bin/activate;", "/env/bin/python","predictprobability.py;" };
public Process startML(){
ProcessBuilder builder = new ProcessBuilder(command_to_run);
Process pr = null;
try {
pr = builder.start();
} catch (IOException ioException) {
System.out.println("error");
}
return pr;
}
public static void main(String[] args){
MLClassifierProcess p = new MLClassifierProcess();
Process pr = p.startML();
if (pr != null)
pr.waitFor();
}
}
Да, похоже, что казнь не удалась. Согласно документации, builder.start() не может вернуть значение null. Значит, это должно вызывать исключение. Ваш код перехватит это исключение и напечатает «ошибку». Это делает это? Если это так, вы должны напечатать исключение, чтобы вы могли видеть, в чем заключается ошибка. При желании вы можете остановиться внутри catch в своем отладчике и таким образом проверить исключение.
Я вижу несколько конкретных вещей: 1) действительно ли ваша виртуальная среда находится в каталоге с именем env в корне вашей файловой системы? 2) Вы уверены, что ваш скрипт python находится в текущем рабочем каталоге, так что он будет найден Python без компонента пути. Вы можете устранить вторую проблему, указав полный путь к вашему скрипту.
В конце концов решение было простым:
Process process = Runtime.getRuntime().exec("<path/to/venv/python_interpreter> "+"path/to/scripytorun.py)
В моем случае успешная команда была
Process process = Runtime.getRuntime().exec( System.getProperty("user.dir")+"/env/bin/python "+System.getProperty("user.dir")+"/predictprobability.py");
process.waitFor();
@CryptoFool был прав, указав, что необходим абсолютный путь к ресурсам, поэтому System.getProperty("user.dir") добавлен к относительным путям.
Это имеет смысл, однако запуск этого кода дает нулевое значение для pr - может ли это означать, что мой command_to_run сформирован неправильно, поэтому мой скрипт не выполняется?