Как получить cpu_times процесса, запускаемого с помощью psutil.Popen, после его завершения, но до его завершения - PullRequest
2 голосов
/ 22 марта 2019

Я хотел бы использовать метод cpu_times() объекта psutil.Popen, чтобы найти кумулятивные значения после его завершения .Сначала я попробовал следующее:

p = psutil.Popen("stress --cpu 3 -v -t 15", shell=True)
p.wait()
cpuTimes = p.cpu_times()

Однако это приводит к исключению NoSuchProcess, поскольку wait() не возвращается до тех пор, пока процесс не будет завершен.Затем я попытался поставить вызов на cpu_times() перед вызовом на wait():

p = psutil.Popen("stress --cpu 3 -v -t 15", shell=True)
cpuTimes = p.cpu_times()
p.wait()

Однако это дает ответ всех нулей.Я предполагаю, что это потому, что он вызывается сразу после запуска процесса.Итак, я добавил вызов к time.sleep(), который просто пережил бы процесс:

p = psutil.Popen("stress --cpu 3 -v -t 15", shell=True)
time.sleep(15.) # b/c -t 15 in subprocess means it will take 15 seconds
cpuTimes = p.cpu_times()
p.wait()

Это фактически дает ожидаемое значение 45 секунд (3 процессора при 100% -ной загрузке в течение 15секунд).

Для общего процесса, однако, я не буду знать, сколько времени потребуется, чтобы закончить.Я хотел бы избежать добавления произвольно большого времени ожидания только для того, чтобы убедиться, что процесс завершен, прежде чем я сделаю запрос.

Есть ли способ узнать, что процесс выполняется без вызова wait() или других подобныхметоды, при возврате которых процесс прекратился?

1 Ответ

1 голос
/ 26 марта 2019

Хорошо, я нашел решение. На самом деле все было довольно просто, поэтому мне, наверное, следовало подумать об этом, прежде чем публиковать свой вопрос, но я думаю, что так иногда и бывает.

p = psutil.Popen("stress --cpu 3 -v -t 15", shell=True)
cpuTimes = p.cpu_times()
while True:
    time.sleep(1e-4)
    cpuTimes = p.cpu_times()  # Make sure to do this before the call to poll()
    retCode = p.poll()
    if retCode is not None:
        break

Здесь я добавил цикл после запуска подпроцесса, который содержит вызовы cpu_times() и poll() методы для процесса.

Метод poll() - это неблокирующий способ проверки завершения подпроцесса. Позвонив по номеру cpu_times() прямо перед вызовом poll(), пройдет крошечный промежуток времени, поэтому мы можем, для всех намерений и целей, рассмотреть последний вызов cpu_times(), чтобы получить точный результат.

Обратите внимание, что мы получили бы исключение при вызове cpu_times() после poll(), если процесс завершен. Это еще одна причина для перевода вызова на номер cpu_times() до вызова на номер poll().

Аргумент к методу sleep() не очень важен, но влияет на то, сколько времени пройдет после завершения подпроцесса и до завершения цикла. Возможно, вы также можете добавить какое-то щедрое время ожидания для защиты от бесконечного цикла, если подпроцесс никогда не завершится.

...