2012-05-23 2 views
6

Mein Python-Programm bereitet Eingaben vor, führt einen externen FORTRAN-Code und verarbeitet die Ausgaben in einer Windows HPC 2008-Umgebung. Es funktioniert großartig, es sei denn, der Code führt das externe Programm zwischen 1042 und 1045 Mal aus (normalerweise konvergiert das Problem früher). In diesen Situationen, erhalte ich eine Ausnahme:"WindowsError: [Fehler 206] Der Dateiname oder die Erweiterung ist zu lang" nach dem Ausführen eines Programms sehr viele Male mit Subprozess

WindowsError: [Error 206] The filename or extension is too long

jedoch an den Dateinamen der Pfad nicht wächst mit der Zeit ist. Es wird nur das Verzeichnis gereinigt und erneut ausgeführt.

Hier ist der Code:

inpF = open(inName) 
outF = open(localOutName,'w') 
p = subprocess.Popen(pathToExe,shell=False,stdin=inpF,stdout=outF,cwd=runPath) 
stdout, stderr = p.communicate() 
outF.close() 
inpF.close() 

pathToExe wird ein konstanter String in einem UNC-Pfad zeigt (zB \\ server \ \ program.exe gemeinsam), ist stdin eine offene Datei im schreibgeschützten Modus auf einem Lokales Laufwerk, stdout ist eine geöffnete Datei im Schreibmodus auf einem lokalen Laufwerk und cwd ist ein lokaler Pfad auf dem Laufwerk C: \. Ich habe bestätigt, dass keines der Argumente für Subprozess länger als 80 Zeichen ist, obwohl das Limit 32.768 sein soll, nach this somewhat related post.

Was mache ich falsch? Irgendwie akkumuliert sich etwas, das erst zum Problem wird, wenn ich tausendmal überlaufe.

UPDATE:

die „zu viele Dateien geöffnet“ Hypothese zu testen, habe ich ein sehr kleines Beispiel, das mit einem anderen ausführbaren sehr schnell läuft. Der Hauptunterschied hier ist, dass die stdin und stdout hier nur leere Dateien sind, während sie im vorherigen Fall beide große Dateien sind. In diesem Fall läuft der Code für 2000 Läufe einwandfrei, während der frühere bei ~ 1042 fehlschlägt. Es gibt also nicht nur so viele Dateien. Vielleicht sind zu viele große Dateien geöffnet?

import subprocess 
for i in range(nRuns): 
    if not (i % (nRuns/10.0)): 
     print('{0:.2}% complete'.format(i/float(nRuns)*100)) 
    inpF=open('in.txt') 
    outF=open('out.txt','w') 
    p = subprocess.Popen('isotxsmerge.exe',shell=False,stdin=inpF, 
           stdout=outF,cwd='.') 
    stdout, stderr = p.communicate() 
    outF.close() 
    inpF.close() 

Antwort

4

hmmm .... eigentlich, ich denke, die Fehlermeldung Text ist ein Red Hering. Ich weiß es nicht genau, aber es scheint mir wahrscheinlich, dass Ihnen die Dateigriffe ausgehen. Aus verschiedenen Quellen scheint es, dass das kanonische Datei-Handle-Limit ungefähr 2048 Dateien ist ... was seltsamerweise in der Nachbarschaft von 2 x Ihrer 1042-Subprozesse liegt. Ich kenne die Interna des Windows-Python-Interpreters nicht, aber meine Vermutung ist, dass die Ziehpunkte nicht schnell genug gesammelt werden, obwohl Sie die Dateien schließen. Nochmal ... das ist nur eine Vermutung ... aber vielleicht ist es eine andere Denkrichtung, die dich zu etwas Schlüssigerem und Produktivem führen könnte.

In der Zwischenzeit können Sie den alten Stand-by-Ansatz verwenden, indem Sie einen Governor-Prozess verwenden, der einen Prozess hervorbringt, der wiederum die Teilprozesse hervorbringt. Der Zwischen-Subprozess hat eine bestimmte Lebensdauer (sagen wir ... nicht mehr als 1000 Subprozesse, die er erzeugt) bevor er stirbt. Wenn der Zwischen-Subprozess abläuft, startet der Governor-Prozess einen neuen. Das ist ein Hack ... und ein tollpatschiger ... aber es funktioniert. (IIRC, der Apache-Webserver hatte eine Art Selbstzerstörungsbegrenzung für die Anzahl der Anfragen, die ein Unterprozess verarbeiten konnte.)

Wie auch immer ... viel Glück und gute Programmierung.

+0

Danke. Ich wette, du hast Recht, dass es ein Ablenkungsmanöver ist. Ich habe die Hypothese der Anzahl der Dateien getestet (siehe Update oben) und konnte das Problem nicht mit einfachen leeren stdin/stdouts reproduzieren. Nicht wirklich schlüssig. – partofthething

Verwandte Themen