如何在完成后但在终止之前使用psutil.Popen运行进程的cpu_times

问题描述 投票:1回答:1

我想使用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个CPU在100%利用率下持续15秒)。

但是,对于一般过程,我不知道完成需要多长时间。我想避免添加任意大的睡眠时间,以确保在我进行查询之前该过程已完成。

有没有办法知道这个过程是在没有调用wait()或其他类似方法的情况下完成的,而这些方法的返回过程终止了?

python subprocess psutil
1个回答
1
投票

好吧,我找到了解决方案。它实际上非常简单,所以在发布我的问题之前我可能应该想到它,但我想这就是这些东西有时会发生的方式。

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()方法的参数不是非常重要,但确实会影响子进程完成后和循环终止之前经过的时间。如果子进程永远不会完成,你可能还可以添加一些慷慨的超时来防止无限循环。

© www.soinside.com 2019 - 2024. All rights reserved.