Java Runtime Exec Python-скрипт с raw_input - PullRequest
0 голосов
/ 03 июня 2018

У меня есть 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();

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

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

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

1 Ответ

0 голосов
/ 04 июня 2018

Вам необходимо унаследовать 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();
  }
}

, а с вашим сценарием

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

Наследование ввода-вывода для 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 time

sys.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 сбросит их (например, при заполнении буфера доlimit).

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), что стандартный вывод сброшен.

...