2013-05-13 13 views
22

Ich benutze Subprozess, um ein anderes Programm aufzurufen und seine Rückgabewerte in einer Variablen zu speichern. Dieser Prozess wird in einer Schleife wiederholt, und nach ein paar tausend Mal das Programm abgestürzt ist mit dem folgenden Fehler:Python-Subprozess: Zu viele geöffnete Dateien

Traceback (most recent call last): 
    File "./extract_pcgls.py", line 96, in <module> 
    SelfE.append(CalSelfEnergy(i)) 
    File "./extract_pcgls.py", line 59, in CalSelfEnergy 
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 
    File "/usr/lib/python3.2/subprocess.py", line 745, in __init__ 
    restore_signals, start_new_session) 
    File "/usr/lib/python3.2/subprocess.py", line 1166, in _execute_child 
    errpipe_read, errpipe_write = _create_pipe() 
OSError: [Errno 24] Too many open files 

Jede Idee, wie dieses Problem zu lösen, ist sehr zu schätzen!

-Code von Kommentaren geliefert:

cmd = "enerCHARMM.pl -parram=x,xtop=topology_modified.rtf,xpar=lipid27_modified.par,nobuildall -out vdwaals {0}".format(cmtup[1]) 
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 
out, err = p.communicate() 
+1

Communicate() schließt die Pipe, das ist also nicht dein Problem. Am Ende ist Popen() nur der Befehl, der ausgeführt wird, wenn Sie keine Pipes mehr haben ... das Problem könnte anderswo in Ihrem Code sein, wenn andere Dateien offen bleiben. Ich habe "SelfE.append" bemerkt ... öffnest du andere Dateien und führst sie in einer Liste auf? – tdelaney

Antwort

10

Ich denke, das Problem auf die Tatsache zurückzuführen war, dass ich die Verarbeitung eine geöffnete Datei mit Subprozess:

cmd = "enerCHARMM.pl -par param=x,xtop=topology_modified.rtf,xpar=lipid27_modified.par,nobuildall -out vdwaals {0}".format(cmtup[1]) 
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 

Hier die cmd varia ble enthält den Namen einer Datei, die gerade erstellt, aber nicht geschlossen wurde. Dann ruft der subprocess.Popen einen Systembefehl für diese Datei auf. Nachdem dies viele Male gemacht wurde, stürzte das Programm mit dieser Fehlermeldung ab.

So ist die Botschaft, die ich daraus gelernt habe, ist

Close the file you have created, then process it

Dank

3

Sie können versuchen, die geöffnete Datei Grenze des OS erhöhen:

ulimit -n 2048

+4

Eigentlich wird dieser Befehl das Limit nicht überschreiten, was über '/ etc/security/limits.conf' gesetzt wurde. Um es zu erhöhen, müssen Sie in dieser Datei Zeilen wie diese einfügen: '* soft nofile 4096'/'* hard nofile 4096' (ersetzen Sie' 4096' durch Ihren eigenen Wert). –

+1

Ich bin gestern in dieses Problem geraten und musste sowohl "/ etc/security/limits.conf" bearbeiten als auch das Limit über "ulimit -n" in ubuntu erhöhen, um diesen Fehler zu beheben. –

0

Datei in subprocess öffnet. Es blockiert den Anruf.

ss=subprocess.Popen(tempFileName,shell=True) 
ss.communicate() 
15

In Mac OSX (El Capitan) aktuelle Konfiguration Siehe:

#ulimit -a 
core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) unlimited 
file size    (blocks, -f) unlimited 
max locked memory  (kbytes, -l) unlimited 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 256 
pipe size   (512 bytes, -p) 1 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 709 
virtual memory   (kbytes, -v) unlimited 

Set geöffneten Dateien Wert auf 10K:

#ulimit -Sn 10000 

Ergebnisse überprüfen:

#ulimit -a 

core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) unlimited 
file size    (blocks, -f) unlimited 
max locked memory  (kbytes, -l) unlimited 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 10000 
pipe size   (512 bytes, -p) 1 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 709 
virtual memory   (kbytes, -v) unlimited 
4

Ein Kindprozess, der von Popen() erstellt wurde, kann offene Dateideskriptoren (eine endliche Ressource) vom übergeordneten Objekt erben. Verwenden Sie close_fds=True auf POSIX (Standard seit Python 3.2), um es zu vermeiden. Auch "PEP 0446 -- Make newly created file descriptors non-inheritable" deals with some remaining issues (since Python 3.4).

+0

Ich glaube nicht, dass das funktioniert, zumindest in allen Fällen. Ich generierte 1200 sleep lawned Prozesse auf einem System mit einem 1024 Open File Limit (Standard unter Ubuntu) und es blies sogar mit close_fds = True. Also ich denke, da ist mehr als das. Da Sie in offenen Prozessen immer noch über dem Limit sind, funktioniert das nur, wenn Sie annehmen, dass das Problem in abgeschlossenen Prozessen liegt, die offene Dateideskriptoren hinterlassen haben. – Sensei

+0

@Sensei es funktioniert: Öffnen Sie Dateien im Eltern (stellen Sie sicher, dass die FDS vererbbar sind) dann spawn Subprozesse mit 'close_fds = False' (beide sind standardmäßig auf alten Python-Versionen, folgen Sie den Links). Sehen Sie, um wie viel früher Sie den Fehler erhalten. Natürlich kann 'close_fds' den Fehler im allgemeinen Fall nicht verhindern: Sie müssen nicht einmal einen neuen Prozess erzeugen, um ihn zu bekommen. – jfs

+0

Außer dass es nicht. Ich habe eine einfache for-Schleife ausgeführt und genügend Subprozesse generiert, um das OS-Limit zu erreichen. Ich habe das mit close_fds = True gemacht. Es hatte keine Auswirkungen. Ich könnte mich irren, warum, aber meine Vermutung ist einfach, dass diese Lösung nur funktioniert, wenn Sie einige Subprozesse generieren und die Deskriptoren nie aufräumen. In einem solchen Fall macht dieses Argument Sinn, aber ich sehe es nicht funktionieren, wenn Sie tatsächlich beabsichtigen, diese vielen Prozesse auf einmal zu erstellen und auszuführen. – Sensei

2

Wie andere erwähnt haben, heben die Grenze in /etc/security/limits.conf und auch war Filedeskriptoren ein Thema für mich persönlich, so habe ich

sudo sysctl -w fs.file-max=100000 

und eine Linie mit fs.file hinzugefügt -max = 100000 /etc/sysctl.conf (nachladen mit sysctl -p)

auch wenn Sie sicherstellen möchten, dass Ihr Prozess nicht durch irgendetwas anderes beeinflusst wird (die Mine war), verwenden

cat /proc/{process id}/limits 

zu finden heraus, was die tatsächlichen Grenzen Ihres Prozesses sind, da für mich die Software, die die Python-Skripte ausführt, auch ihre Grenzen hatte, die die systemweiten Einstellungen außer Kraft gesetzt haben.

Veröffentlichen Sie diese Antwort hier nach der Auflösung meines speziellen Problems mit diesem Fehler und hoffentlich hilft es jemandem.

Verwandte Themen