Wiederholt in stdin schreiben und von stdout eines Prozesses aus python lesen

8

Ich habe einen Fortran-Code, der einige Zahlen aus STDIN liest und Ergebnisse in STDOUT schreibt. Zum Beispiel:

%Vor%

So kann ich das Programm von einer Shell aus starten und die folgende Sequenz von Eingängen / Ausgaben erhalten:

5.0
25.0
2.5
6.25

Jetzt muss ich das in Python machen. Nach dem vergeblichen Ringen mit dem Subprozess.Popen und durch alte Fragen auf dieser Seite zu sehen, entschied ich mich, pexpect.spawn zu verwenden:

%Vor%

und es funktioniert. Das Problem ist, dass die real Daten, die ich zwischen Python und meinem Fortran-Programm übergeben muss, ein Array von 100.000 (oder mehr) Double-Genauigkeits-Floats sind. Wenn sie in einem Array namens x enthalten sind, dann

%Vor%

überschreitet die Zeit mit der folgenden Fehlermeldung von pexpect:

%Vor%

es sei denn, x hat weniger als 303 Elemente. Gibt es eine Möglichkeit, große Datenmengen an STDIN / STDOUT eines anderen Programms zu übergeben?

Ich habe versucht, die Daten in kleinere Stücke zu teilen, aber dann verliere ich ein Los in der Geschwindigkeit.

Vielen Dank im Voraus.

    
TM5 17.08.2010, 15:02
quelle

5 Antworten

5

Ich habe eine Lösung gefunden, die das Unterprozessmodul verwendet, also poste ich es hier als Referenz, wenn jemand dasselbe tun muss.

%Vor%

Die Klasse wird mit einem externen Programm namens 'optimizer' wie folgt aufgerufen:

%Vor%

Auf der Fortran-Seite (dem Programm, das kompiliert wurde, um dem ausführbaren 'Optimierer' zu geben) würde ein Vektor mit 500 Elementen so eingelesen werden:

%Vor%

und würde so geschrieben werden:

%Vor%

und das war's! Ich habe es mit Zustandsvektoren bis zu 200.000 Elementen getestet (was die Obergrenze dessen ist, was ich gerade brauche). Hoffe, das hilft jemand anderem als mir. Diese Lösung funktioniert mit ifort und xlf90, aber nicht mit gfortran aus irgendeinem Grund, den ich nicht verstehe.

    
TM5 03.12.2010 09:00
quelle
1

Beispiel squarer.py Programm (es passiert einfach in Python, verwenden Sie Ihre Fortran-Programmdatei):

%Vor%

Beispiel target.py Programm:

%Vor%

Die Funktion main enthält den Code, den Sie verwenden werden: richten Sie ein Companion -Objekt ein, companion.send eine lange Datenzeile, companion.recv eine Zeile. Wiederholen Sie dies bei Bedarf.

    
tzot 16.09.2010 13:17
quelle
0

Ich denke, dass Sie hier nur einen Zeilenumbruch hinzufügen:

%Vor%

statt einen pro Zeile hinzuzufügen.

    
Alexander Kjäll 17.08.2010 15:09
quelle
0

Sieht so aus, als würden Sie das Zeitlimit überschreiten (Standard-Timeout, glaube ich, 30 Sekunden), weil das Vorbereiten, Senden, Empfangen und Verarbeiten dieser vielen Daten viel Zeit in Anspruch nimmt. Pro die Dokumente , timeout= ist ein optionaler benannter Parameter für die Methode expect , die Sie nicht aufrufen - - Vielleicht gibt es eine undokumentierte Methode, um das Standard-Timeout im Initialisierer zu setzen, das gefunden werden könnte, indem man über die Quellen geht (oder im schlimmsten Fall durch das Hacken dieser Quellen).

Wenn das Fortran-Programm 100 Einträge gleichzeitig liest und speichert (mit einer Eingabeaufforderung), wird die Synchronisierung sehr viel einfacher. Könnten Sie Ihren Fortran-Code für diesen Zweck modifizieren, oder würden Sie lieber den undokumentierten / Hack-Ansatz wählen?

    
Alex Martelli 17.08.2010 15:12
quelle
0

Hier ist eine große Vereinfachung: Brechen Sie Ihre Python in zwei Dinge.

%Vor%

Die squarer -Anwendung ist Ihr Fortran-Code. Liest von stdin, schreibt nach stdout.

Dein source.py ist dein Python, der

macht %Vor%

Oder vielleicht etwas ein bisschen einfacher, d. h.

%Vor%

Und dein sink.py ist so etwas.

%Vor%

Die Trennung von Quelle, Quadrierer und Senke ergibt 3 separate Prozesse (statt 2) und verwendet mehr Kerne. Mehr Kerne == mehr Gleichzeitigkeit == mehr Spaß.

    
S.Lott 17.08.2010 15:33
quelle

Tags und Links