2017-01-23 12 views
1

Java 프로그램을 통해 Raspberry Pi에서 Python 스크립트를 조율하려고합니다. 나는 내부에 무한 루프가있는 파이썬 코드를 가지고 있는데, 초음파 센서로부터 거리를 읽어서 콘솔로 출력한다. Java 코드는이를 쉘 프로세스로 호출 한 다음 프로세스의 OutputStream을 읽습니다. 내가 겪고있는 문제는 데이터가 대량으로 도착한다는 것입니다. 파이썬 스크립트가 콘솔로 출력 할 때마다 새 값을 얻지 않고 10 초마다 새로운 데이터를 얻습니다. 거의 실시간으로 웹 대시 보드에 데이터를 표시하려고하기 때문에 문제가됩니다.셸 스크립트에서 생성 된 Java InputStream에서 읽기가 일괄 처리로 발생합니다.

다이어그램은 다음과 같습니다

이 출력 스트림에서 읽을 새 스레드 (별도의 클래스를) 인스턴스화 래퍼 클래스입니다 :

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

자바 코드는 다음과 같습니다 파이썬 스크립트의.

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

그리고 파이썬 코드는 지금과 같은 (간단한 거리 측정 코드를 약간 수정 버전) :

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

물론 Jim, 원래 질문을 수정하겠습니까? –

+1

출력을 생성하는 프로세스가 출력을 버퍼링합니다. Java 코드에서 그렇게 할 수있는 방법은 없습니다. 파이썬 코드를 수정하십시오. 주의 :'Reader' 또는'InputStream'에서 읽는 쓰레드는 비 차단이 될 수 없습니다. 또한 독서 스레드가 출력을 목록에 축적 할 때 버퍼링이 중요한 이유는 완전히 불분명합니다. – EJP

답변

0

감사합니다 여러분 모두 도와 주셔서. EJP는 버퍼링 문제를 해결했습니다. 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()