从 shell 脚本生成的 Java InputStream 中读取是分批进行的
Reading from a Java InputStream generated by a shell script happens in batches
我正在尝试通过 Java 程序在 Raspberry Pi 上编排 Python 脚本。我有一些 Python 代码,里面有一个无限循环,可以读取超声波传感器的距离并将其输出到控制台。 Java 代码将其称为 shell 进程,然后读取进程的 OutputStream。我遇到的问题是数据成批到达。我不是每次 Python 脚本输出到控制台时都获得一个新值,而是每 10 秒左右获得一次新数据。这是有问题的,因为我试图在网络仪表板上近乎实时地显示数据。
图表如下所示:
DistanceController
|--getDistance(public)
|--getBufferSize(public)
|--buffer(private)
|--DistanceThread(private)
|--bufferReference (private)
|--PythonScriptProcess
Java代码如下:
这是一个包装器 class,它实例化一个新线程(单独的 class)以从 Python 脚本的输出流中读取。
public class DistanceController {
private DistanceThread distanceThread;
private Thread t;
private LinkedList<DistanceVT> buffer = new LinkedList<DistanceVT>();
public DistanceController()
{
t = new Thread(distanceThread);
t.start();
}
public DistanceVT getDistance() {
return buffer.getLast();
}
}
这是读取距离的线程,思路是非阻塞的。
public class DistanceThread implements Runnable {
private LinkedList<DistanceVT> buffer;
private String[] args = new String[]{"python", "./run-scripts/distance.py"};
public DistanceThread(LinkedList<DistanceVT> list) {buffer = list;}
@Override
public void run() {
while (true) {
try {
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
final Process p = pb.start();
while (true) {
InputStream s = p.getInputStream();
final BufferedReader reader = new BufferedReader(new InputStreamReader(s));
while (((line = reader.readLine()) != null)) {
buffer.add(parseDistance(line));
}
}
} catch (Exception e) {
//handle errors
}
}
}
而 Python 代码看起来像这样(最简单的距离测量代码的稍微修改版本):
import time
import datetime
from random import randint
def measure_distance():
time.sleep(0.1)
return randint(10,15)
while True:
distance = measure_distance()
print ("%s,%s" % (datetime.datetime.now(),distance))
谢谢大家的帮助。 EJP 解决了缓冲问题 - 在 Python 代码中添加 sys.stdout.flush() 解决了问题。
至于其他问题-你是对的。我的意思是因为我是在一个单独的线程上阅读,程序的主线程可以继续做其他逻辑。
读取线程将数据累积在创建它的 class 传递给它的列表中。然后可以通过此包装器访问此数据 class,而无需等待输出完成。
import time
import datetime
from random import randint
import sys
def measure_distance():
time.sleep(0.1)
return randint(10,15)
while True:
distance = measure_distance()
print ("%s,%s" % (datetime.datetime.now(),distance))
sys.stdout.flush()
我正在尝试通过 Java 程序在 Raspberry Pi 上编排 Python 脚本。我有一些 Python 代码,里面有一个无限循环,可以读取超声波传感器的距离并将其输出到控制台。 Java 代码将其称为 shell 进程,然后读取进程的 OutputStream。我遇到的问题是数据成批到达。我不是每次 Python 脚本输出到控制台时都获得一个新值,而是每 10 秒左右获得一次新数据。这是有问题的,因为我试图在网络仪表板上近乎实时地显示数据。
图表如下所示:
DistanceController
|--getDistance(public)
|--getBufferSize(public)
|--buffer(private)
|--DistanceThread(private)
|--bufferReference (private)
|--PythonScriptProcess
Java代码如下:
这是一个包装器 class,它实例化一个新线程(单独的 class)以从 Python 脚本的输出流中读取。
public class DistanceController {
private DistanceThread distanceThread;
private Thread t;
private LinkedList<DistanceVT> buffer = new LinkedList<DistanceVT>();
public DistanceController()
{
t = new Thread(distanceThread);
t.start();
}
public DistanceVT getDistance() {
return buffer.getLast();
}
}
这是读取距离的线程,思路是非阻塞的。
public class DistanceThread implements Runnable {
private LinkedList<DistanceVT> buffer;
private String[] args = new String[]{"python", "./run-scripts/distance.py"};
public DistanceThread(LinkedList<DistanceVT> list) {buffer = list;}
@Override
public void run() {
while (true) {
try {
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
final Process p = pb.start();
while (true) {
InputStream s = p.getInputStream();
final BufferedReader reader = new BufferedReader(new InputStreamReader(s));
while (((line = reader.readLine()) != null)) {
buffer.add(parseDistance(line));
}
}
} catch (Exception e) {
//handle errors
}
}
}
而 Python 代码看起来像这样(最简单的距离测量代码的稍微修改版本):
import time
import datetime
from random import randint
def measure_distance():
time.sleep(0.1)
return randint(10,15)
while True:
distance = measure_distance()
print ("%s,%s" % (datetime.datetime.now(),distance))
谢谢大家的帮助。 EJP 解决了缓冲问题 - 在 Python 代码中添加 sys.stdout.flush() 解决了问题。
至于其他问题-你是对的。我的意思是因为我是在一个单独的线程上阅读,程序的主线程可以继续做其他逻辑。
读取线程将数据累积在创建它的 class 传递给它的列表中。然后可以通过此包装器访问此数据 class,而无需等待输出完成。
import time
import datetime
from random import randint
import sys
def measure_distance():
time.sleep(0.1)
return randint(10,15)
while True:
distance = measure_distance()
print ("%s,%s" % (datetime.datetime.now(),distance))
sys.stdout.flush()