Question

Je dois limiter la quantité de temps et cpu pris par des applications de ligne de commande externes I Spawn à partir d'un processus de python en utilisant subprocess.call, principalement parce que parfois le processus est bloqué et donné naissance à l'épingle cpu à 99%.

agréable et ulimit semblent comme des moyens raisonnables pour ce faire, mais je ne sais pas comment ils avaient interagir avec le sous-processus.

  • Les limites ressemblent à:
    • Tuer le processus si elle prend plus de 60 secondes
    • Limiter à 20% de cpu
  • Je veux appliquer la ressource limitant à la sous-processus, pas au processus de python qui est fraie les sous-processus.

Y at-il un moyen d'appliquer agréable et ulimit au processus pondu subprocess.call? Y at-il de meilleures alternatives natif python?

Ceci est un système Linux (ubuntu).

Était-ce utile?

La solution

Vous pouvez définir des limites pour les sous-processus avec des commandes shell ulimit et nice comme ceci:

import subprocess
subprocess.Popen('ulimit -t 60; nice -n 15 cpuhog', shell=True)

Cela va cpuhog avec une limite de 60 secondes de temps CPU et un réglage de niceness de 15. Notez qu'il n'y a aucun moyen simple de définir un accélérateur de CPU 20% en tant que tel. Le processus utilisera 100% du CPU à moins qu'un autre processus (moins bien) a également besoin du CPU.

Autres conseils

Utilisez le paramètre preexec_fn à subprocess.Popen, et le module de ressources. Exemple:

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 fourchette dans un nouveau processus. Dans le nouveau processus, il appellera setLimits (), puis exec child.py . Cela signifie que la ressource sera limitée dans le processus de l'enfant, mais pas dans le parent.

sortie lorsque le programme en cours d'exécution:

./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)

Ceci est dans de nombreux cas, une meilleure solution que d'essayer d'utiliser ulimit, car il est pas toujours une bonne idée de se reproduire sous-processus via le shell, en particulier car il provoque souvent le paramètre laid citant des problèmes.

Erik , il était facile pour moi, mais il a oublié la partie qui nice Rich Souligné. Je trouve le paquet psutil agréable (jeu de mots) mais malheureusement moins portable. Voici mon opinion à la question suivante:

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 a utilisé le shell=True auquel je suis en quelque sorte allergique. Peut-être que je suis vieux et grincheux, mais je tente de l'éviter!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top