psutil.cpu_percent()首次调用返回0.0是设计使然,需预热一次并间隔≥0.1秒再调用才有效;内存用psutil.virtual_memory().percent直接获取百分比。

如何用 psutil 获取 CPU 和内存的实时使用率
直接调用 psutil.cpu_percent() 和 psutil.virtual_memory().percent 即可,但要注意:首次调用 psutil.cpu_percent() 总是返回 0.0,必须间隔至少 0.1 秒再调一次才有意义。
常见错误是写成单次采集就打印,结果看到全是 0;正确做法是先调一次“预热”,再进循环采集:
import psutil
import time
<p>psutil.cpu_percent() # 预热,丢弃这次结果
time.sleep(0.1)</p><p>while True:
cpu = psutil.cpu_percent(interval=0.5)
mem = psutil.virtual_memory().percent
print(f"CPU: {cpu:.1f}%, MEM: {mem:.1f}%")
time.sleep(1)</p>
-
interval参数设为0.5表示采样 0.5 秒内的平均占用,值太小(如0.1)可能波动剧烈,太大(如2)响应滞后 -
psutil.virtual_memory()返回命名元组,.percent是已用百分比,不是剩余;别误用.available直接除总内存算 - Windows 下
cpu_percent(percpu=True)可能因内核计数器延迟导致某核短暂飙到 >100%,属正常现象
怎样监控每个进程的 CPU 和内存占用并排序
用 psutil.process_iter() 遍历进程,但必须加异常捕获——很多进程(尤其是系统进程)在迭代中途可能已退出,直接访问属性会抛 psutil.NoSuchProcess。
典型场景是想找出最吃资源的前 5 个进程,按 CPU 或内存降序排:
def get_top_processes(n=5, sort_by="cpu_percent"):
procs = []
for p in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_info']):
try:
if p.info['cpu_percent'] is not None and p.info['cpu_percent'] > 0:
procs.append(p.info)
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
return sorted(procs, key=lambda x: x[sort_by], reverse=True)[:n]
<h1>用法</h1><p>top_cpu = get_top_processes(sort_by="cpu_percent")
top_mem = get_top_processes(sort_by="memory_info")</p>
-
process_iter()的attrs参数指定要预取的字段,能显著减少后续访问开销;不传则每次访问都触发系统调用 -
memory_info()返回的是namedtuple,含rss(实际物理内存)和vms(虚拟内存),别直接拿整个对象当数值用 - Linux 下对容器内进程,
cpu_percent()可能返回None,需判空,否则sorted会报TypeError
为什么 psutil.disk_usage() 在某些路径下报 FileNotFoundError
这不是权限问题,而是路径不存在或尚未挂载。比如监控 /mnt/data,但该目录是 NFS 挂载点,服务未启动时路径为空,disk_usage() 就会直接抛异常,不会返回 None。
- 务必用
os.path.exists()或os.path.ismount()做前置检查,尤其在 Docker 或云环境里挂载点动态变化很常见 -
psutil.disk_partitions()可列出当前所有已挂载分区,配合device或mountpoint过滤更可靠 - Windows 下盘符如
"D:"必须带冒号和反斜杠结尾("D:\"),否则disk_usage("D:")会失败
脚本长期运行时内存泄漏和句柄堆积怎么避免
psutil 自身不泄漏,但用户代码容易在循环中不断创建 Process 对象却不释放引用,尤其用 psutil.Process(pid) 手动构造后又没显式 del 或重用。
- 优先用
process_iter()的attrs预取模式,避免在循环里反复 newProcess实例 - 若必须保留进程引用(如持续跟踪某 PID),记得在进程退出后手动
del p,或用weakref管理 - Linux 下频繁调用
net_connections()会快速耗尽 socket 描述符,建议只在需要时调用,并用kind='inet'限制协议族
真实生产环境里,最常被忽略的是日志频率和采样精度的平衡——每 100ms 打一次日志,跑一周就能写满几十 GB,而把 interval 设成 0 并不等于“实时”,它只是复用上次的内核快照,本质仍是离散采样。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











