如何使用Python获取准确的进程CPU和内存使用情况?

16

我正在尝试创建一个进程监视器,但是与 Windows 任务管理器相比,我的结果并不准确。

我一直在使用 psutil,当查看整体 CPU 和内存使用情况时似乎工作正常,但是对于单个进程来说似乎不太准确。内存使用始终高于任务管理器,而 CPU 则总是随机的。

我在初始化时使用 self.process = psutil.Process(self.pid) 设置进程,然后每秒调用下面的方法,任务管理器中的进程以恒定的 5.4% 的 CPU 使用率和 130MB RAM 运行,但下面的代码产生了:

CPU: 12.5375
Memory 156459008
CPU: 0.0
Memory 156459008
CPU: 0.0
Memory 156459008
CPU: 0.0
Memory 156459008
CPU: 12.5375
Memory 156459008
CPU: 0.0
Memory 156459008
CPU: 0.0
Memory 156459008

示例代码:

def process_info(self):    
        # I am calling this method twice because I read the first time gets ignored?
        ignore_cpu = self.process.cpu_percent(interval=None) / psutil.cpu_count()
        time.sleep(0.1)
        process_cpu = self.process.cpu_percent(interval=None) / psutil.cpu_count()
        
        # I also tried the below code but it was much worse than above
        # for j in range(10):
        #     if j == 0:
        #         test_list = []
        #     p_cpu = self.process.cpu_percent(interval=0.1) / psutil.cpu_count()
        #     test_list.append(p_cpu)
        # process_cpu = (sum(test_list)) / len(test_list)

        # Memory is about 25mb higher than task manager
        process_memory = self.process.memory_info().rss

        print(f"CPU: {process_cpu}")
        print(f"Memory: {process_memory}")

我是否在错误地使用psutil,或者有更精确的方法来获取数据?


我认为Windows任务管理器可能仅基于简单性能原因而不是100%正确,因为它会grep所有进程而不是一个。 - Axeltherabbit
谢谢回复,也许是这种情况,并且可能会调整我的问题,我不关心获取准确的 CPU 和内存使用情况,我想获取Windows任务管理器使用的值,因为这就是目前的测量方法,因此改变这个基准会使它更好或更差。 - Chris
3
我认为你希望将其更改为显示一段时间内的平均值而不是单个时刻的值,进程在某个时间点上不使用CPU是正常的,我建议查看给定时间段内的中位数或类似指标,任务管理器显示的内存使用可能存在差异,因为其并不十分精确,但你可以参考类似的开源软件如TOP/HTOP来获取想法。 - Axeltherabbit
3个回答

6
我认为你误解了psutil.cpu_percent()的输出。 它返回一个浮点数,表示当前系统范围内的CPU利用率百分比。当interval > 0.0时,将进程时间与间隔之前和之后经过的系统CPU时间进行比较(阻塞)。当间隔为0.0或None时,将进程时间与自上次调用以来经过的系统CPU时间进行比较,并立即返回。这意味着第一次调用它时,它将返回一个有意义的0.0值,其后续调用可以基于此。在这种情况下,为了准确性,建议至少相隔0.1秒调用一次该函数。
因此,如果你使用interval=0.1调用它,则它将返回进程在最近0.1秒内运行的时间百分比。 如果你使用interval=None调用它,则它将返回自上次调用以来进程运行的时间百分比。 如果你连续两次使用interval=None调用它,则第一次调用将返回自上次调用以来进程运行的时间百分比,而第二次调用将返回自上次调用以来进程运行的时间百分比。 因此,如果你想获取进程在最近0.1秒内运行的时间百分比,应该使用interval=0.1调用它。

谢谢您解释它的工作原理,您是正确的,我误解了输出结果,但是我也尝试了您建议的方法(请参见我的示例中被注释掉的代码),但它给出了一些非常随机的结果。 - Chris

1

正如@Axeltherabbit在评论中所提到的,任务管理器会获取给定名称下的所有进程,而psutils则会获取一个单独的进程。 psutils是正确的,任务管理器过度范围并决定获取所有进程。


这并没有解释为什么数字不同。有没有文档显示哪个更准确? - Navin
它确实解释了为什么数字不同,因为它从上述位置提取数字。psutils文档应该解释清楚这一点。 - ShadowProgrammer

0

我认为这样会更准确吧?

    import psutil

for process in [psutil.Process(pid) for pid in psutil.pids()]:
    try:
        process_name = process.name()
        process_mem = process.memory_percent()
        process_cpu = process.cpu_percent(interval=0.5)
    except psutil.NoSuchProcess as e:
        print(e.pid, "killed before analysis")
    else:
        print("Name:", process_name)
        print("CPU%:", process_cpu)
        print("MEM%:", process_mem)

这仅适用于系统信息,而不适用于单个进程: “Process”对象没有属性“virtual_memory” TypeError:Process.cpu_percent()收到意外的关键字参数“percpu” - Chris
不,谢谢尝试,但这会得到与上面示例中相同的结果,只是内存现在是以百分比而不是大小为单位。 - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接