Python: ulimit e agradável para subprocess.call / subprocess.Popen?
Pergunta
Eu preciso limitar a quantidade de tempo e cpu tomada pela linha de comando externo aplicativos que eu desova de um processo de python usando subprocess.call, principalmente porque, por vezes, o processo gerado fica preso e pins da CPU em 99%.
agradável e ulimit parecer maneiras razoáveis ??de fazer isso, mas não tenho certeza de como eles interagem com subprocesso.
- Os limites algo como:
- matar o processo se ele está tomando mais de 60 segundos
- limitá-lo a 20% da cpu
- Eu quero aplicar o recurso limitante ao subprocesso, não para o processo de python que está gerando os subprocessos.
Existe uma maneira de aplicar agradável e ulimit para o processo subprocess.call gerou? Existem alternativas melhores python-natal?
Esta é em um sistema Linux (Ubuntu).
Solução
Você pode definir limites para subprocessos com os ulimit
e nice
comandos shell como este:
import subprocess
subprocess.Popen('ulimit -t 60; nice -n 15 cpuhog', shell=True)
Este é executado cpuhog
com um limite de 60 segundos de tempo de CPU e um ajuste de niceness de 15. Note que não há nenhuma maneira simples de definir um acelerador CPU 20% como tal. O processo vai usar 100% da CPU, a menos que outro processo (menos bom) também precisa da CPU.
Outras dicas
Use o parâmetro preexec_fn para subprocess.Popen, eo módulo de recursos. Exemplo:
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 seguirão em um novo processo. No novo processo, ele irá chamar setlimits (), em seguida, exec child.py . Isto significa que o recurso será limitado no processo de criança, mas não no pai.
Saída durante a execução do 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)
Esta é em muitos casos uma solução melhor do que tentar usar ulimit, uma vez que nem sempre é uma boa idéia para subprocess desova via shell, especialmente desde que muitas vezes provoca parâmetro problemas citando feio.
Erik tornou fácil para mim, mas ele esqueceu a parte nice
quais Rico out Pointed. I encontrar o pacote agradável psutil
(trocadilho intencional), mas, infelizmente, menos portátil. Aqui é a minha opinião com a pergunta:
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 usou o shell=True
para o qual eu sou de alguma forma alérgica. Talvez eu sou apenas velho e mal-humorado aqui, mas tento evitá-lo!