我使用
在我的java应用程序中启动python脚本Process p = Runtime.getRuntime().exec("python script.py");
此脚本在循环中运行,仅由事件(或用户交互)取消。脚本在每个循环周期写入输出,一些文本如" 12:22:35 - Heartbeat"
while True:
print("Heartbeat")
time.sleep(1)
在我的Java应用程序中,我希望在显示时读取此输出。我的问题是,如果我使用BufferReader,它将等到进程完成后再读取输出。以下是我的阅读方式:
BufferedReader is = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = is.readLine()) != null)
System.out.println(line);
如何阅读输出" live"?
为了更好地理解:python-script监听硬件按钮,当按下该按钮时,会写出一些输出。在我的java应用程序中,我想显示此消息并将其发送给某些客户端。
答案 0 :(得分:3)
使用https://github.com/zeroturnaround/zt-exec
new ProcessExecutor().command("python", "script.py")
.redirectOutput(new LogOutputStream() {
@Override
protected void processLine(String line) {
...
}
})
.execute();
答案 1 :(得分:1)
我经常写一些类似的东西:
class StreamHandler extends Thread {
InputStream is;
Writer writer;
StreamHandler(InputStream is, Writer writer) {
super("StreamHandler");
this.is = is;
this.writer = writer;
}
@Override
public void run() {
try (InputStreamReader isr = new InputStreamReader(is)) {
char buffer[] = new char[256];
int n;
while ((n = isr.read(buffer)) > 0) {
writer.write(buffer, 0, n);
}
} catch (IOException e) {
System.err.println("StreamHandler: " + e);
}
}
}
虽然我已经将它用于捕获输出流到我自己的缓冲区,但您可以实时回显到stdout
,如:
Process process = Runtime.getRuntime().exec(...);
Writer writer = new OutputStreamWriter(System.out);
StreamHandler stdout_handler = new StreamHandler(process.getInputStream(), writer);
stdout_handler.start();
答案 2 :(得分:0)
尝试将您的python代码更改为:
while True:
print("Heartbeat", flush=True)
time.sleep(1)
我一直在努力做同样的事情并在这个问题上找到了这个解决方案:PumpStreamHandler can capture the process output in realtime
答案 3 :(得分:0)
如果只想打印到当前进程的流,则可以使用ProcessBuilder
类创建一个进程,并使其“继承” IO流,如下所示:
Process process = new ProcessBuilder()
.command(commandList)
.directory(workingDirectory)
.inheritIO()
.start();
或者,如果您想更好地控制流,
Process process = new ProcessBuilder()
.command(commandList)
.directory(workingDirectory)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectInput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.start();
同样,这可能会或可能不会适合您的情况,并且取决于程序正在运行的终端。我尝试在系统终端中使用Java程序运行mysql
和python
命令行解释器,并且运行良好。
但是,如果您想将输出重定向到其他地方,则该进程的标准输出将被缓冲(请参见here)。并且在您的情况下,仅在程序完成时才刷新缓冲区。因此,像在答案中提到的@Mateus Terra之类的在flush=True
中设置print
的事情可能会起作用。