Domanda

devo limitare la quantità di tempo e CPU presa da esterni applicazioni a riga di comando che Spawn da un processo Python usando subprocess.call, soprattutto perché a volte il processo generato si blocca e blocca il CPU al 99%.

bello e ulimit sembrano modi ragionevoli per fare questo, ma io non sono sicuro di come si erano interagiscono con sottoprocesso.

  • I limiti sono qualcosa del tipo:
    • Uccidere il processo se si sta prendendo più di 60 secondi
    • limitarla al 20% della cpu
  • voglio applicare la risorsa limitando al sottoprocesso, non al processo di pitone che sta generando i sottoprocessi.

C'è un modo per applicare bello e ulimit al subprocess.call processo generato? Ci sono migliori alternative python-native?

Questo è su un sistema Linux (Ubuntu).

È stato utile?

Soluzione

È possibile impostare dei limiti per sottoprocessi con i comandi di shell ulimit e nice come questo:

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

Questo esegue cpuhog con un limite di 60 secondi di tempo di CPU ed una regolazione di priorità di 15. Si noti che non esiste un modo semplice per impostare un acceleratore CPU 20% come tale. Il processo sarà utilizzare il 100% della CPU a meno che un altro (meno bello) processo deve anche la CPU.

Altri suggerimenti

Utilizzare il parametro preexec_fn a subprocess.Popen, e il modulo di risorse. Esempio:

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 si biforca in un nuovo processo. Nel nuovo processo, chiamerà setlimits (), poi exec child.py . Questo significa che la risorsa sarà limitato nel processo figlio, ma non nel genitore.

Output quando si programma in esecuzione:

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

Questo è in molti casi una soluzione migliore che cercare di usare ulimit, dato che non è sempre una buona idea per deporre le uova sottoprocesso via shell, soprattutto dal momento che è spesso causa di brutto parametro guai citando.

Erik ha reso facile per me, ma ha dimenticato la parte nice che Rich a punta fuori. Trovo il pacchetto psutil bello (gioco di parole), ma purtroppo meno portabile. Ecco il mio prendere la questione:

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 utilizza il shell=True per cui sono in qualche modo allergica. Forse sono solo vecchio e scontroso qui, ma cerco di evitarlo!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top