我有一个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()); }