Java runtime exec скрипт python с raw_input

Nox Noctis спросил: 10 мая 2018 в 04:47 в: java

У меня есть java-программа, которая запускает скрипт python (сценарий не мой и поэтому не может быть изменен). Я запускаю скрипт с помощью

Process p = Runtime.getRuntime().exec("python myScript.py");

В сценарии есть строка «raw_input», которая ожидает ввода пользователя. Я попытался использовать

BufferedWriter userInput = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
userInput.write("myInput");

Но это не похоже работать.

Другое дело, я читаю вывод с помощью

BufferedReader stdInput = new BufferedReader(new
                    InputStreamReader(p.getInputStream()));
List<String> output = new ArrayList();
while ((s = stdInput.readLine()) != null) {
                output.add(s);
            }

Это работает, когда скрипт python не ожидает ввода, но когда есть input_raw (), stdInput.readLine () просто застрял.

Пример сценария python:

name = raw_input("What is your name? ")
print "your name is "+name

Вся программа:

public static void main(String args[]) {    PythonRunner pr = new PythonRunner();    pr.start();    while(!pr.isFinished){
        try {
            System.out.println("waiting...");
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }    for(String s:pr.result) System.out.println(s);
}public class PythonRunner extends Thread {public List<String> result;
public boolean isFinished;public PythonRunner() {
    result= new ArrayList<>();
    isFinished = false;
}@Override
public void run(){
    try {
        Process p = Runtime.getRuntime().exec("python myScript.py");        BufferedWriter userInput = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));        BufferedReader stdInput = new BufferedReader(new
                InputStreamReader(p.getInputStream()));        userInput.write("myInput");        String s;
        while ((s = stdInput.readLine()) != null) {
             result.add(s);
        }        isFinished=true;
    }
    catch (IOException e) {
        isFinished=true;
    }}
}

РЕДАКТИРОВАТЬ: Мне удалось дать скрипту ввод с помощью

userInput.write(cmd);
userInput.newLine();
userInput.flush();

Однако у меня все еще есть проблемы считывая выход. Некоторые из скриптов имеют бесконечный цикл ввода-& gt; print.force, скрипт:

stop = False
while not stop:
    name = raw_input("")
    print "your name is "+name
    if name == "stop":
        stop = True

Пока этот скрипт работает, я не могу читать выходные данные уже заданных имен .. Только когда процесс задана команда «stop», могу ли я прочитать весь вывод.

1 ответ

Есть решение
mko ответил: 12 мая 2018 в 11:27

Вам нужно наследовать IO

https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#inheritIO ()

Устанавливает источник и назначение для стандартного ввода-вывода подпроцесса как те, которые соответствуют текущему процессу Java. Это удобный метод. Вызов формы

pb.inheritIO()

Затем ваше выполнение процесса может принимать следующую форму

public class ProcessSample {
 public static void main(String [] arg) throws Exception {
   ProcessBuilder pb =
      new ProcessBuilder("python", "script.py").inheritIO();
    Process p = pb.start();
    p.waitFor();
  }
}

, а с вашей script

name = raw_input("What is your name? ")
print "your name is "+name

вы можете выполнить

> javac ProcessSample.java
> java -cp . ProcessSample
What is your name? a
your name is a

Унаследовать IO для stdout

Вы всегда можете передать некоторые значения в код Python и в то же время считывать значения из stdout - наследуя его.

import java.io.*;public class PythonProcessRedirect {  public static void main(String [] arg) throws Exception {    ProcessBuilder pb =
      new ProcessBuilder("python", "script_raw.py");
    pb.redirectErrorStream(true);
    pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
    Process p = pb.start();    BufferedWriter writer = new BufferedWriter( new OutputStreamWriter( p.getOutputStream() ));
    String input = "2\n";
    writer.write(input);
    writer.flush();    p.waitFor();
  }
}

Обратите внимание, что для непрерывного потока данных вам необходимо его сбросить

import sys
import timesys.stdout.write("give some input: ")
sys.stdout.flush()
time.sleep(2)
line = sys.stdin.readline()
sys.stdout.write("you typed: " + line)
sys.stdout.flush();

в противном случае данные будут доступны не раньше, чем Python сбрасывает их (например, путем заполнения буфера до предела).

Stream Gobbler

Вы также можете пойти с Stream Gobbler и запустить отдельные потоки для stdin / stdout / stderr.

import java.io.*;public class PythonProcessStreamGobblerIO {  public static void main(String [] arg) throws Exception {    final Process p = Runtime.getRuntime().exec("python ./script_os.py" );    new Thread() {
      public void run() {
        try {
          BufferedWriter writer = new BufferedWriter( new OutputStreamWriter( p.getOutputStream() ));
          String input = "2\n";
          writer.write(input);
          writer.flush();
        } catch(Exception ex) {
          ex.printStackTrace();
        }
      }
    }.start();    new Thread() {
      public void run() {
        try {
          Reader reader = new InputStreamReader(p.getInputStream());  
          int data = -1;
          while((data =reader.read())!= -1){
            char c = (char) data;
            System.out.print(c);
          }
          reader.close();
        } catch(Exception ex) {
          ex.printStackTrace();
        }
      }
    }.start();    p.waitFor();
  }
}

Но, опять же, вы должны убедиться (на стороне Python), что stdout очищается.

Nox Noctis ответил: 12 мая 2018 в 09:40
Не уверен, что я понимаю .. Таким образом, пользователь должен запустить java-программу и ввести свой ввод. Это не моя цель. У меня уже есть вход (в примере - "myInput") в примере, и мне нужно, чтобы программа автоматически передавала его скрипту python.
Nox Noctis ответил: 12 мая 2018 в 01:17
Действительно, проблема была в флеше. Я закончил работать с Python -u, и это решило.

Дополнительное видео по вопросу: Java runtime exec скрипт python с raw_input

Cool Java Tricks - Call an external program

Python Programming Tutorial - 8 - Raw Input

Python Tutorial for Beginners 5 - Save and Run Python files .py