Python: ulimit y agradable para subprocess.call / subprocess.Popen?
Pregunta
necesito para limitar la cantidad de tiempo de CPU y tomada por las aplicaciones de línea de comandos externos que desovan de un proceso de Python usando subprocess.call, sobre todo porque a veces el proceso generado se queda atascado y los pasadores de la CPU en un 99%.
agradable y ulimit parecen razonables maneras de hacer esto, pero no estoy seguro de cómo habían interactúan con subproceso.
- Los límites de ser algo como:
- Matar el proceso si está teniendo más de 60 segundos
- limitarlo a 20% de la CPU
- Quiero solicitar el recurso limitante para el subproceso, no al proceso de pitón que está generando los subprocesos.
¿Hay una manera de aplicar agradable y ulimit a la subprocess.call proceso generado? ¿Hay mejores alternativas pitón-natal?
Esto es en un sistema Linux (ubuntu).
Solución
Puede establecer límites para subprocesos con los comandos de shell y ulimit
nice
como esta:
import subprocess
subprocess.Popen('ulimit -t 60; nice -n 15 cpuhog', shell=True)
Esto ejecuta cpuhog
con un límite de 60 segundos de tiempo de CPU y un ajuste de la amabilidad de 15. Nota que no hay manera simple de establecer un acelerador CPU 20% como tal. El proceso va a utilizar 100% de la CPU a menos que otra (menos bonito) proceso también necesita la CPU.
Otros consejos
Utilice el parámetro preexec_fn a subprocess.Popen, y el módulo de recursos. Ejemplo:
parent.py:
#!/usr/bin/env python
import os
import sys
import resource
import subprocess
def setlimits():
# Set maximum CPU time to 1 second in child process, after fork() but before exec()
print "Setting resource limit in child (pid %d)" % os.getpid()
resource.setrlimit(resource.RLIMIT_CPU, (1, 1))
print "CPU limit of parent (pid %d)" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)
p = subprocess.Popen(["./child.py"], preexec_fn=setlimits)
print "CPU limit of parent (pid %d) after startup of child" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)
p.wait()
print "CPU limit of parent (pid %d) after child finished executing" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)
child.py:
#!/usr/bin/env python
import os
import sys
import resource
print "CPU limit of child (pid %d)" % os.getpid(), resource.getrlimit(resource.RLIMIT_CPU)
parent.py se bifurcará en un nuevo proceso. En el nuevo proceso, se llamará setLimits (), a continuación, exec child.py . Esto significa que el recurso estará limitado en el proceso hijo, pero no en los padres.
Salida cuando se ejecuta el programa:
./parent.py
CPU limit of parent (pid 17404) (-1, -1)
Setting resource limit in child (pid 17405)
CPU limit of parent (pid 17404) after startup of child (-1, -1)
CPU limit of child (pid 17405) (1, 1)
CPU limit of parent (pid 17404) after child finished executing (-1, -1)
Esto es en muchos casos una solución mejor que tratar de utilizar ulimit, ya que no es siempre una buena idea para desovar subproceso mediante el intérprete, sobre todo porque a menudo causa problemas parámetro fea citando.
Erik hizo fácil para mí, pero se olvidó la parte nice
que Rich Señaló. Me parece que el paquete de psutil
agradable (juego de palabras), pero por desgracia menos portátiles. Aquí está mi tomar ante la pregunta:
import os
import psutil
import resource
import subprocess
def preexec_fn():
pid = os.getpid()
ps = psutil.Process(pid)
ps.set_nice(10)
resource.setrlimit(resource.RLIMIT_CPU, (1, 1))
print "mother pid", os.getpid()
p = subprocess.Popen(["./cpuhog.sh"], preexec_fn=preexec_fn)
p.wait()
print "mother still alive with pid", os.getpid()
Ville utiliza el shell=True
a la que estoy de alguna manera alérgica. Tal vez sólo soy viejo y gruñón aquí, pero trato de evitarlo!