Java:有没有办法在执行期间运行系统命令并打印输出?

时间:2013-09-30 20:14:43

标签: java python unix stream output

我有一个python脚本,需要很长时间才能完成。我想从Java运行它,但也在执行时输出脚本的输出,这样我就可以判断它是否正常运行。

我已经搜索并且只找到了在系统命令完成后输出输出的示例,而不是在执行期间输出。

在脚本运行时以任何方式执行此操作?

这就是我所拥有的

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);
    }
}

4 个答案:

答案 0 :(得分:3)

我设法让它像这样工作(注意它需要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)的正常行为。

答案 1 :(得分:2)

  

我搜索过,只找到了输出后输出的例子   系统命令已完成,而不是在执行期间。

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

您可以尝试直接从BufferedReader读取,而不是使用InputStream,因为在流程退出之前,可能无法满足readLine所需的条件。

我还建议您直接使用ProcessBuilder而不是Process,因为除了其他任何内容之外,它还允许您将错误流的输出重定向到输入流中,只读一个流而不是两个......

这也可能是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似乎在将其发送到stdout之前将其缓冲出来。我不认为你可以在Java方面解决这个问题,但需要改变Python的运行方式或脚本的工作方式。

有关详细信息,请参阅How to flush output of Python print?

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

我怀疑你写的是stderr,你看不到因为你在stdin上阻塞了。使用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()
写到stdout后