2016-01-25 5 views
6

Ich spawn einen Prozess von Common Lisp-Programm (gnuplot). Ich kann Ein- und Ausgabeströme für den Prozess einrichten. Ich habe jedoch ein Problem beim Lesen von der Ausgabe. Das Problem ist, dass ich versuchen möchte, aus der Ausgabe zu lesen, und wenn da nichts ist, naja ... tue nichts zum Beispiel.Wie erkennt man, ob der Eingabestream leer ist (aber nicht EOF)?

(Grundproblem: Ich möchte show term das Ergebnis des Befehls lesen, aber ich möchte andere Ausgabe überspringen, dass gnuplot könnte vor dem Senden Sie diesen Befehl erzeugt haben)

Wenn ich nur (read-line gnuplot-output nil :eof) verwenden und es gibt nichts in Ausgangsstrom, wird es nicht :eof anzeigen (da der Strom noch am Leben ist und etwas dort erscheinen könnte) und wird nur blockieren, bis es etwas zu lesen hat (dh für immer).

Gibt es eine Möglichkeit zu erkennen, dass nichts zu lesen ist? Zumindest kann der Versuch, den Lesevorgang irgendwie sicher zu unterbrechen, beendet werden (d. H. Es sollte keine neue Zeile aus dem Stream entfernt werden, sobald das Timeout erreicht ist).

PS. Ich verwende SBCL

Antwort

5

Listen sollte Ihnen sagen, ob ein Zeichen verfügbar ist. Ich denke, Sie müssen den Stream Zeichen für Zeichen und nicht ganze Zeilen gleichzeitig lesen, es sei denn, Sie sind sicher, dass das Programm nie eine unvollständige Zeile ausgibt.

Edit: Ein schneller Test (sb-ext für die Ausführung des Programms):

(defun test() 
    (do* ((program (run-program "output-test.sh" nil 
           :search t 
           :output :stream 
           :wait nil)) 
     (output-stream (process-output program))) 
     ((not (process-alive-p program))) 
    (if (listen output-stream) 
     (loop 
      for char = (read-char-no-hang output-stream nil nil) 
      while char 
      do (write-char char)) 
     (format t "No output available.~%")) 
    (sleep 1))) 

Wo output-test.sh ist:

#!/bin/sh 
for item in * 
do 
    echo $item 
    sleep 3 
done 
+1

1+ Für OP: siehe auch 'read-char-no-hang' – coredump

+0

Mit' read-char-no-hang' brauchen Sie 'listen' nicht zu verwenden. Auch das Zusammenlegen von Variablenbindungen von einem äußeren 'let' /' let * 'zum inneren' do'/'do *' wie in einer Ihrer Bearbeitungen behindert die Lesbarkeit und Wartbarkeit des Codes, nur um ein paar Zeichen zu sparen. Sowohl 'program' als auch' output-stream' variieren nicht in der Schleife, so dass sie in einem äußeren 'let' /' let * 'liegen würden. – acelent

+0

@acalent Das 'listen' soll prüfen, ob etwas zu lesen ist, ohne es zu lesen. Wenn nur 'read-char-no-hang' verwendet wird, wird das erste Zeichen der Eingabe konsumiert, wodurch die Logik komplizierter wird. Was die Variablenbindungen in einem separaten "let" anbelangt, dachte ich, dass das zunächst klarer wäre, aber da die Schleife so lange ausgeführt werden sollte, bis das Programm beendet wird, ist es sinnvoll, das Programm in den Schleifen zu starten Initialisierung. Auf diese Weise ist die gesamte Lebensdauer des Kindprozesses an einem Ort. – jkiiski

Verwandte Themen