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()
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
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
Vous pouvez essayer d'augmenter la limite de fichiers ouverts du système d'exploitation:
ulimit -n 2048
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) .
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.
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()
.
ouvre le fichier dans le sous-processus. Il bloque l'appel.
ss=subprocess.Popen(tempFileName,Shell=True)
ss.communicate()