Java:有没有办法运行系统命令并在执行过程中输出输出?

我有一个Python脚本,需要很长时间才能完成。 我想从Java运行它,而且在执行时输出脚本的输出,以便我可以判断它是否正常运行。

我search了,只发现了在系统命令完成后输出输出的例子,而不是在执行过程中。

任何方式来执行脚本运行?

这是我的

public void doSomething() throws IOException { String[] callAndArgs = {"python", "/hi.py"}; Process p = Runtime.getRuntime().exec(callAndArgs); BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream())); String s; while ((s = stdInput.readLine()) != null) { System.out.println(s); } while ((s = stdError.readLine()) != null) { System.out.println(s); } } 

我设法让它像这样工作(注意它需要java7):

 package test; import java.lang.ProcessBuilder.Redirect; public class Test { public static void main(String... args) throws Exception { ProcessBuilder pb = new ProcessBuilder("python","/home/foobar/Programming/test/src/test/test.py"); pb.redirectOutput(Redirect.INHERIT); Process p = pb.start(); p.waitFor(); } } 

python(注意我刷新python使它使用sys.stdout.flush())

 import time,sys c =0 while c<=50: time.sleep(1) print("----") c = c +1 sys.stdout.flush() 

注意,如果你不想在一个循环中刷新,你可以使用这个:

 ProcessBuilder pb = new ProcessBuilder("python","-u","/home/foobar/Programming/NetBeansProjects/test/src/test/test.py"); 

Redirect.INHERIT

指示子进程I / O源或目标将与当前进程的相同。 这是大多数操作系统命令解释器(shell)的正常行为。

我搜索了,只发现了在系统命令完成后输出输出的例子,而不是在执行过程中。

这很奇怪,因为您的示例应该在执行命令时转储输出。

您可以尝试直接从InputStream读取,而不是使用BufferedReader ,因为readLine所需的条件可能不会被满足,直到该过程退出。

我还建议你直接使用ProcessBuilder ,除此之外,它允许你将输出从错误流重定向到输入流,允许你只读取一个流,而不是两个。

这可能也是一个Python的问题,以及如何刷新它的输出缓冲区…

例如,而不是等待BufferedReader决定何时返回,请尝试从流中打印每个字符/报告

  ProcessBuilder pb = new ProcessBuilder("test.py"); pb.redirectError(); Process p = pb.start(); InputStream is = null; try { is = p.getInputStream(); int in = -1; while ((in = is.read()) != -1) { System.out.print((char)in); } } finally { try { is.close(); } catch (Exception e) { } } 

更新

做一点点阅读,Python似乎在将它发送到标准输出之前将其缓冲出来。 我不认为你可以在Java方面解决这个问题,但是需要改变Python的运行方式或脚本的工作方式。

请参阅如何刷新Python打印的输出? 更多细节

我怀疑你正在写信给stderr,你不能看到,因为你在标准输入阻塞。 使用ProcessBuilder而不是执行exec 。 这样,您可以将stderr和stdin重定向到单个流中。

这里是一个例子:

 import java.io.*; public class Test { public static void main(String... args) throws IOException { ProcessBuilder pb = new ProcessBuilder("test.py"); pb.redirectErrorStream(true); Process proc = pb.start(); Reader reader = new InputStreamReader(proc.getInputStream()); BufferedReader bf = new BufferedReader(reader); String s; while ((s = bf.readLine()) != null) { System.out.println(s); } } } 

或者,你可以产生线程分别从stdin / stderr读取。

另一个要寻找的是输出缓冲由python。 你可以看到这是否是由于做的原因:

 import sys sys.stdout.flush() 

写入标准输出之后

在while循环中不要使用#readLine作为条件。 而是将你的inputStream包装在扫描器中,并使用#hasNextLine()

  Scanner in = new Scanner(p.getInputStream()); while (in.hasNextLine()) { System.out.println(in.nextLine()); }