Java运行时执行带有raw_input的python脚本 - java

我有一个运行python脚本的Java程序(该脚本不是我的,因此无法更改)。
我使用以下命令运行脚本:

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

运行此脚本时,我似乎无法读取已经给定名称的输出。.仅当给该进程“ stop”命令时,我才能读取整个输出。

参考方案

您需要继承IO

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

  将子流程标准I / O的源和目标设置为
  与当前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

为标准输出继承IO

您始终可以将一些值传递给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刷新之前立即可用(例如,通过将缓冲区填充到最大限制)。

溪流狼人

您还可以使用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。

Java-搜索字符串数组中的字符串 - java

在Java中,我们是否有任何方法可以发现特定字符串是字符串数组的一部分。我可以避免出现一个循环。例如String [] array = {"AA","BB","CC" }; string x = "BB" 我想要一个if (some condition to tell wheth…

Java RegEx中的单词边界\ b - java

我在使用\b作为Java Regex中的单词定界符时遇到困难。对于text = "/* sql statement */ INSERT INTO someTable"; Pattern.compile("(?i)\binsert\b");找不到匹配项Pattern insPtrn = Pattern.compile(&…

Java Double与BigDecimal - java

我正在查看一些使用双精度变量来存储(360-359.9998779296875)结果为0.0001220703125的代码。 double变量将其存储为-1.220703125E-4。当我使用BigDecimal时,其存储为0.0001220703125。为什么将它双重存储为-1.220703125E-4? 参考方案 我不会在这里提及精度问题,而只会提及数字…

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java

我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…