2017-12-21 6 views
0

ich eine Verarbeitungskette, die entlang dieser Linien geht:Persistent subprocess Pipeline - lesen stdout ohne

  1. Preprocess Daten in wenigen Schritten, die ruft Perl, Bash und Python-Skripte von einer einzelnen Bash-Skript enthalten, Verbindungs diejenigen, die über Rohre
  2. Transformation von Daten in Python (das Programm, das ich leider verwenden laufe nicht auf Python 3, so dass ich glaube, ich bin 2.7 gezwungen, laufen)
  3. Nachbearbeiten Daten wie in der Vorverarbeitungsschritt

Eine Möglichkeit, dies vorher gearbeitet hat, ist

cat input | preprocess.sh | transform.py | postprocess.sh 

Und das funktioniert gut mit der Verarbeitung von Chargen von Eingangsdaten.

Allerdings muss ich dies jetzt als Server-Funktionalität in Python implementieren - ich muss in der Lage sein, ein einzelnes Datenelement zu akzeptieren, die Pipeline auszuführen und sie schnell wieder auszuspucken.

Der zentrale Schritt, den ich gerade aus Python heraus anrufe, ist der einfache Teil. Die Nachbearbeitung ist auch relativ einfach.

Hier ist das Problem: der Vorverarbeitungscode besteht aus 4 verschiedenen Skripten, von denen jedes Daten an die nächste ausgibt und von denen zwei Modelldateien von der Festplatte in den Arbeitsspeicher laden müssen. Dieses Laden ist relativ langsam und macht schreckliche Dinge zu meiner Ausführungszeit. Ich denke also, ich muss sie irgendwie im Gedächtnis behalten, schreibe an ihre stdin s und lese die Ausgabe.

Allerdings finde ich, dass für jeden einzelnen Link in meiner Kette, kann ich nicht zu stdin schreiben und lesen stdout ohne stdin zu schließen, und das würde das Verfahren unbrauchbar machen, wie ich würde dann den Prozess wieder öffnen muß, und laden Sie die Modell erneut.

Sie beachten Sie, dass dies kein Problem mit meiner Skripte ist, wie für jedes Glied in der Kette

cat input_data | preprocessing_script_i.sh 

kehrt genau das, was es soll innerhalb von Bash.

Hier sind die Dinge, die ich versucht habe bis jetzt:

  • einfach zu schreiben, um stdin und flush es - wartet auf unbestimmte Zeit auf Readline-
  • process.communicate - tötet den Prozess und ist somit nicht in Frage.
  • indem Master- und Slave-pty Griffen - hängt an Readline-
  • eine Warteschlange und ein Gewinde Verwendung stdout zu lesen, während auf stdin vom Hauptthread
  • Herumspielen Schreiben mit bufsize im Aufruf von subprocess

Gibt es eine Möglichkeit, dies von Python aus zu tun? Ist das überhaupt möglich, wenn ich das bezweifle? Kann ich diese Pipeline (ohne die Elemente zu berühren, wie es für meinen Anwendungsfall nicht möglich ist) in einer anderen Sprache neu implementieren?

+1

Könnten Sie eine Named Pipe (FIFO) verwenden, statt stdout und stdin zu verketten? – Hannu

+0

@Hannu Ich kann vielleicht, sobald ich herausfinden, was das ist - habe nicht von der Named Pipe Begriff gehört. Ich werde nach einigem googeln wieder zu dir kommen! – Perfi

+1

'os.mkfifo ("/tmp/mypipe ")' würde Sie erstellen. Oder Sie können es in der Shell mit 'mknod/tmp/mypipe p' machen. Sie können dies als eine Datei für Lese- und Schreibzwecke behandeln und von einem Prozess schreiben und von einem anderen lesen. – Hannu

Antwort

0

Es tut mir Leid, schlug die Ideen waren großartig und das ist wahrscheinlich viele Menschen gehen in die Zukunft, aber das ist, wie ich das Problem gelöst nicht zu helfen.

Es stellt sich heraus, perl hat eine -b Flag für den Druck in Linie gepufferten Modus. Sobald ich das in den perl -b script.perl Teil der Verarbeitungspipeline einsteckte, begannen sich Sachen glatt zu bewegen und das einfache process.write(), das von .flush() gefolgt wurde, war genug, die Ausgabe zu erhalten.

Ich werde versuchen, die Frage Tags und Titel zu ändern, um das tatsächliche Problem besser zu passen.

1

Die einfachste Möglichkeit besteht darin, mv Dateien aus demselben Dateisystem (da Umbenennung Atom über Dateioperationen ist, während cp nicht atomare ist) zu einem "Eingabeverzeichnis". Die Shell-Schleife unendlich und wartet auf eine neue Datei mv zu "Arbeitsverzeichnis" verarbeitet es und mv es in "done-Verzeichnis" oder "Fehlerverzeichnis".

+0

Lassen Sie mich sicherstellen, dass ich Sie richtig verstehe: meinst du eine Art von Schleife in Bash, die nach Dateien im 'input'-Verzeichnis sucht (das ich aus Python erstellen könnte), dann irgendwelche neuen vorbearbeitet und sie nach' verschiebt Ausgabe "? Oder meinst du das irgendwie aus Python? Jede Python-Implementierung hat möglicherweise das gleiche Problem, dass der Subprozess mehrere Male geöffnet werden muss, es sei denn, 'stdin' und' stdout' können irgendwie hot-swapped werden (um neue Dateien zu berücksichtigen). Können Sie? – Perfi

+0

Ja, ich spreche über die Bash-Shell, anstatt aus einer Pipe Lesen aus verschiedenen Dateien zu lesen, können die Verzeichnisse einmal per Konvention definiert werden, Dateien sollten auch eine Konvention haben, um den Aufrufer-Prozess zu identifizieren, so dass es Ergebnis in getan finden konnte, 'error' ist nur eine Idee, aber es scheint, dass es hier nicht hilft –

+0

aber Python sollte Dateien zuerst in einem anderen Verzeichnis erstellen und sie in Eingabe verschieben, um Race Condition zu vermeiden –

1

Sie könnten stdin/stdout Probleme im Zusammenhang mit einem FIFO

os.mkfifo("/tmp/fifo") 

Anschließend können Sie verwenden, um dies aus Python als Datei zum Lesen und Schreiben Zwecke von verschiedenen Prozessen vermeiden, und man kann sogar in die Fifo peek (Python: Check if named pipe has data) in Ihrem Leser zu überprüfen, ob dort etwas zu lesen ist.

Wenn nichts davon hilft, wäre ein weiterer Ansatz Inter mit einer Messaging-Plattform Prozesskommunikation zu ersetzen. ZeroMQ (zmq) ist einfach zu implementieren und benötigt keine Server-Komponenten, und Sie würden dann Verkettung von Ein- und Ausgängen loswerden. Sie würden nur Nachrichten von einem Prozess veröffentlichen und sie von einem anderen lesen. Daten werden übertragen, aber mit einem gewundenen Leser würden Sie nicht mit blockierenden E/A stecken bleiben.

Verwandte Themen