web-dev-qa-db-fra.com

Python Sous-processus: trop de fichiers ouverts

J'utilise un sous-processus pour appeler un autre programme et enregistrer ses valeurs de retour dans une variable. Ce processus est répété en boucle et après quelques milliers de fois, le programme s'est écrasé avec l'erreur suivante:

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

Toute idée sur la façon de résoudre ce problème est très appréciée!

Code fourni à partir des commentaires:

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()
37
Vahid Mirjalili

Je suppose que le problème était dû au fait que je traitais un fichier ouvert avec un sous-processus:

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)

Ici, la variable cmd contient le nom d'un fichier qui vient d'être créé mais pas fermé. Puis le subprocess.Popen appelle une commande système sur ce fichier. Après avoir fait cela plusieurs fois, le programme s'est écrasé avec ce message d'erreur.

Donc, le message que j'ai appris de ceci est

Fermez le fichier que vous avez créé, puis traitez-le

16
Vahid Mirjalili

Sous Mac OSX (El Capitan) Voir la configuration actuelle:

#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

Définissez fichiers ouverts valeur à 10K:

#ulimit -Sn 10000

Vérifiez les résultats:

#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
26
user260826

Vous pouvez essayer d'augmenter la limite de fichiers ouverts du système d'exploitation:

ulimit -n 2048

7
Matt Sweeney

Un processus enfant créé par Popen() peut hériter des descripteurs de fichiers ouverts (une ressource finie) du parent. Utilisation close_fds=True sur POSIX (par défaut depuis Python 3.2), pour l'éviter. De plus, "PEP 0446 - Rendre les descripteurs de fichiers nouvellement créés non héritables" traite de certains problèmes restants (depuis Python 3.4) .

5
jfs

Comme d'autres l'ont remarqué, augmenter la limite dans /etc/security/limits.conf et aussi les descripteurs de fichiers était un problème pour moi personnellement, donc je l'ai fait

Sudo sysctl -w fs.file-max=100000 

Et ajouté une ligne avec fs.file-max = 100000 à /etc/sysctl.conf (recharger avec sysctl -p)

Aussi, si vous voulez vous assurer que votre processus n'est affecté par rien d'autre (qui était le mien), utilisez

cat /proc/{process id}/limits 

pour savoir quelles sont les limites réelles de votre processus, comme pour moi le logiciel exécutant les scripts python a également eu ses limites qui ont outrepassé les paramètres à l'échelle du système.

Publier cette réponse ici après avoir résolu mon problème particulier avec cette erreur et j'espère que cela aide quelqu'un.

2
Soniku

Vous invoquez peut-être la commande plusieurs fois. Si oui, chaque fois que vous faites stdout=subprocess.PIPE. Entre chaque appel, essayez de faire p.stdout.close().

2
Jyogo

ouvre le fichier dans le sous-processus. Il bloque l'appel.

ss=subprocess.Popen(tempFileName,Shell=True)
 ss.communicate()
0
imp