Вопрос

Мне нужно ограничить количество времени и процессор, занимаемые внешними приложениями командной строки, которые я запускаю из процесса Python с помощью subprocess.call , главным образом потому, что иногда порожденный процесс зависает и фиксирует процессор на 99%.

nice и ulimit кажутся разумными способами сделать это, но я не уверен, как они будут взаимодействовать с подпроцессом.

  • Ограничения выглядят примерно так:
    • Завершите процесс, если он занимает более 60 секунд.
    • Ограничьте его до 20% процессора
  • Я хочу применить ограничение ресурсов к подпроцессу, а не к процессу Python, который порождает подпроцессы.

Есть ли способ применить nice и ulimit к процессу, порожденному subprocess.call?Есть ли лучшие альтернативы Python?

Это в системе Linux (Ubuntu).

Это было полезно?

Решение

Вы можете установить ограничения для подпроцессов с помощью ulimit и nice такие команды оболочки:

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

Это работает cpuhog с ограничением процессорного времени в 60 секунд и поправкой приятности 15.Обратите внимание, что не существует простого способа установить дросселирование ЦП на 20 % как таковое.Процесс будет использовать 100% ЦП, если только другому (менее приятному) процессу не понадобится ЦП.

Другие советы

Используйте параметр preexec_fn для subprocess.Popen и модуля ресурсов.Пример:

родитель.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)

ребенок.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)

родитель.py разветвится на новый процесс.В новом процессе он вызовет setlimits(), а затем выполнит child.py.Это означает, что ресурс будет ограничен в дочернем процессе, но не в родительском.

Вывод при запуске программы:

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

Во многих случаях это лучшее решение, чем попытка использовать ulimit, поскольку не всегда хорошая идея запускать подпроцесс через оболочку, особенно потому, что это часто вызывает неприятные проблемы с кавычками параметров.

Эрик облегчил мне задачу, но он забыл nice часть, которая Богатый Указал.Я нахожу psutil упаковка хорошая (каламбур), но, к сожалению, менее портативная.Вот мой взгляд на вопрос:

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()

Вилле использовал shell=True на который у меня почему-то аллергия.Возможно я здесь просто старый и сварливый, но стараюсь этого избегать!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top