2013-05-13 2 views
22

Sto utilizzando un sottoprocesso per chiamare un altro programma e salvare i suoi valori di ritorno su una variabile. Questo processo viene ripetuto in un ciclo, e dopo un paio di migliaia di volte il programma si è schiantato con il seguente errore:Sottoprocesso Python: troppi file aperti

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 

Qualsiasi idea di come risolvere questo problema è molto apprezzato!

codice fornito da commenti:

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() chiude la pipe, quindi non è un problema. Alla fine, Popen() è solo il comando che viene eseguito quando si esauriscono le pipe ... il problema potrebbe essere altrove nel codice con altri file lasciati aperti. Ho notato "SelfE.append" ... stai aprendo altri file e li stai tenendo in una lista? – tdelaney

risposta

10

Credo che il problema era dovuto al fatto che stavo elaborando un file aperto con sottoprocesso:

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) 

Qui il cmd varia ble contiene il nome di un file appena creato ma non chiuso. Quindi lo subprocess.Popen chiama un comando di sistema su quel file. Dopo aver fatto questo per molte volte, il programma si è bloccato con quel messaggio di errore.

Quindi il messaggio che ho imparato da questo è

Close the file you have created, then process it

Grazie

3

Puoi provare ad aumentare il limite di file aperti del sistema operativo:

ulimit -n 2048

+4

In realtà quel comando non aumenterà il limite sopra quello che è stato impostato in '/ etc/security/limits.conf'. Per aumentarlo, è necessario posizionare linee come queste * * soft nofile 4096'/'* hard nofile 4096' in quel file (sostituire' 4096' con il proprio valore). –

+1

Sono rientrato in questo problema ieri, e ho dovuto modificare entrambi/etc/security/limits.conf' e aumentare il limite tramite 'ulimit -n' in ubuntu per superare questo errore. –

0

apre file in sottoprocesso. Sta bloccando la chiamata.

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

In Mac OSX (El Capitan) Vedi configurazione corrente:

#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 file aperti valore a 10K:

#ulimit -Sn 10000 

verificare i risultati:

#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

Un processo figlio creato da Popen() può ereditare i descrittori di file aperti (una risorsa finita) dal genitore. Utilizzare close_fds=True su POSIX (predefinito da Python 3.2), per evitarlo. Inoltre, "PEP 0446 -- Make newly created file descriptors non-inheritable" deals with some remaining issues (since Python 3.4).

+0

Non penso che funzioni, almeno in tutti i casi. Ho generato 1200 processi di sonno generati su un sistema con un limite di 1024 file aperti (predefinito su Ubuntu) e si è verificato anche con close_fds = True. Quindi penso che ci sia dell'altro. Dal momento che hai comunque superato il limite nei processi aperti e questo funziona solo se si presuppone che il problema risiede nei processi finiti che hanno lasciato i descrittori di file aperti. – Sensei

+0

@Sensei funziona: apre i file nel genitore (assicurati che i file fds siano ereditabili), quindi genera i sottoprocessi con 'close_fds = False' (entrambi sono predefiniti su vecchie versioni di Python, seguono i collegamenti). Guarda quanto prima otterrai l'errore. Ovviamente 'close_fds' non può impedire l'errore nel caso generale: non è nemmeno necessario generare un nuovo processo, per ottenerlo. – jfs

+0

Tranne che non è così. Ho eseguito un ciclo for semplice e generato sottoprocessi sufficienti per raggiungere il limite del sistema operativo. L'ho fatto con close_fds = True. Non ha avuto impatto. Potrei sbagliarmi sul perché, ma la mia ipotesi è semplicemente che questa soluzione funziona solo se si generano alcuni sottoprocessi e non si puliscono mai i descrittori. In tal caso, questa argomentazione ha senso, ma non la vedo funzionare se effettivamente si intende generare ed eseguire tutti quei processi contemporaneamente. – Sensei

2

Come altri hanno notato, aumentare il limite di /etc/security/limits.conf e anche file descrittori era un problema per me personalmente, così ho fatto

sudo sysctl -w fs.file-max=100000 

E ha aggiunto una linea con fs.file -max = 100000 a /etc/sysctl.conf (ricaricare con sysctl -p)

Inoltre, se si vuole fare in modo che il processo non è influenzato da qualsiasi altra cosa (che la mia era), utilizzare

cat /proc/{process id}/limits 

trovare fuori da ciò che sono i veri limiti del tuo processo, come per me il software che esegue gli script Python ha anche i suoi limiti applicati che hanno scavalcato le impostazioni del sistema.

Inserendo questa risposta qui dopo aver risolto il mio particolare problema con questo errore e si spera che aiuti qualcuno.