2017-01-23 3 views
1

Javaプログラムを使用してRaspberry PiでPythonスクリプトをオーケストレーションしようとしています。私は、超音波センサーからの距離を読み取り、それをコンソールに出力する無限ループを備えたPythonコードをいくつか持っています。 Javaコードはこれをシェルプロセスとして呼び出し、そのプロセスをOutputStreamで読み取ります。私が経験している問題は、データが大きなバッチで到着することです。 Pythonスクリプトがコンソールに出力するたびに新しい値を取得するのではなく、10秒ごとに新しいデータを取得します。これは、Webダッシュボードにほぼリアルタイムでデータを表示しようとしているため問題になります。シェルスクリプトによって生成されたJava InputStreamからの読み込みがバッチで行われる

図は次のようになります。

DistanceController 
    |--getDistance(public) 
    |--getBufferSize(public) 
    |--buffer(private) 
    |--DistanceThread(private) 
      |--bufferReference (private) 
      |--PythonScriptProcess 

Javaコードは以下の通りです:

これは、出力ストリームから読み取るための、新しいスレッド(別のクラス)をインスタンス化するラッパークラスです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)) 
+0

問題を再現するために必要なコードを最小限に抑えることはできますか? –

+0

もちろんジム、元の質問を編集しますか? –

+1

出力を生成するプロセスがバッファリングしています。 Javaコードでこれについて何もできることはありません。 Pythonコードを修正してください。 'Reader'ま​​たは' InputStream'からのスレッドの読み込みは、非ブロッキングではない可能性があります。また、バッファリングがなぜ重要か、読み取りスレッドがリストに出力を蓄積するだけでは、まったく不明です。 – EJP

答えて

0

おかげで、あなたのすべてのあなたの助けを。 EJPはバッファリングの問題を解決しました。問題を解決したPythonコードにsys.stdout.flush()を追加しました。

他の質問については、あなたが正しいです。私は別のスレッドで読んでいるので、プログラムのメインスレッドは他のロジックを実行することができます。

読み取りスレッドは、データを作成したクラスによって渡されたリストにデータを蓄積します。このデータは、出力が完了するのを待たずに、このラッパー・クラスを介してアクセスできます。

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() 
関連する問題