psutil.process_iter() 返回一个生成器,每次yield一个psutil.process实例;直接print只显示生成器对象地址,需遍历并用try/except安全访问属性。

psutil.process_iter() 返回的是什么,为什么不能直接 print
调用 psutil.process_iter() 得到的是一个生成器(generator),不是列表,也不是进程对象本身——它每次 yield 一个 psutil.Process 实例。直接 print(psutil.process_iter()) 只会看到类似 <generator object process_iter at></generator> 的输出,毫无意义。
常见错误是写成:
for p in psutil.process_iter():
print(p) # 这样只打印 Process 对象地址,看不出进程名和 PID
正确做法是主动获取属性,比如 p.pid、p.name()、p.status()。但要注意:某些进程可能已被系统回收,此时访问属性会抛出 psutil.NoSuchProcess 异常。
- 必须用
try/except包裹属性访问逻辑 - 推荐只取少量稳定字段,如
pid、name()、status();避免调用cmdline()或username()等易触发权限错误或异常的属性 - 如果需要排序或筛选,先转成列表再处理(但注意内存开销)
如何安全遍历并显示进程名、PID 和状态
最轻量、最稳定的显示方式是只读取三项:PID、进程名、运行状态。这些字段几乎总能成功获取,且不依赖额外权限(Linux/macOS 普通用户、Windows 非管理员也可运行)。
示例代码:
import psutil
<p>for proc in psutil.process_iter():
try:
pinfo = proc.as_dict(attrs=['pid', 'name', 'status'])
print(f"{pinfo['pid']:6} {pinfo['name'][:15]:15} {pinfo['status']}")
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass</p>
这里用了 proc.as_dict() 一次性取多个字段,并自动跳过无权访问或已消亡的进程。比逐个调用 p.pid + p.name() 更高效,也更健壮。
-
as_dict()的attrs参数必须传 list,不能传 tuple 或 str - Windows 下某些系统进程(如
System Idle Process)PID 为 0,status()可能返回idle,这是正常行为 - 若需过滤掉内核线程(Linux),可加判断:
if not pinfo['name'].startswith('kthreadd')
想按 CPU 或内存排序?别在遍历时实时计算
调用 p.cpu_percent() 或 p.memory_info() 会触发采样逻辑,首次调用返回 0.0,第二次才开始有值——这意味着你无法在单次遍历中可靠获取实时占用率。强行调用还可能导致 psutil.AccessDenied(尤其在 macOS 或受限 Windows 账户下)。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
如果真要排序,分两步走:
- 第一轮遍历:只收集
pid和name(),存入列表 - 调用一次
psutil.cpu_percent(percpu=False)或psutil.virtual_memory()做全局快照(非必需,仅用于上下文) - 第二轮:对已知 PID 构造新
Process实例(psutil.Process(pid)),再调用cpu_percent(interval=0.1)——注意 interval 至少 0.1 秒才有意义
简单排序显示内存占用前 10 的进程(需两次遍历):
procs = []
for p in psutil.process_iter(['pid', 'name']):
try:
procs.append(p.info)
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
<h1>按内存 RSS 排序(需单独抓取)</h1><p>sorted_procs = []
for p in procs:
try:
proc = psutil.Process(p['pid'])
mem = proc.memory_info().rss
sorted_procs.append((p['pid'], p['name'], mem))
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue</p><p>sorted_procs.sort(key=lambda x: x[2], reverse=True)
for pid, name, rss in sorted_procs[:10]:
print(f"{pid:6} {name[:15]:15} {rss // 1024 // 1024} MB")</p>
Windows 下看不到完整命令行?那是权限问题
调用 p.cmdline() 在 Windows 默认权限下大概率触发 psutil.AccessDenied,即使你是管理员,也可能因 UAC 或服务进程隔离而失败。这不是代码 bug,是系统限制。
绕过方法有限:
- 以管理员身份运行 Python 脚本(右键 → “以管理员身份运行”)
- 改用
wmic process get name,processid,commandline命令(但输出格式难解析,且 Win11 后 wmic 正逐步弃用) - 接受现实:普通用户脚本不应依赖
cmdline(),它本就不是跨平台稳定字段
macOS 和 Linux 下 cmdline() 通常可用,但要注意:空列表表示进程已退出或被内核隐藏(如某些容器 init 进程)。
真正容易被忽略的点是:psutil 的进程对象不是快照,而是对内核状态的实时引用。遍历耗时越长,中间进程状态变化越多——所以不要假设“循环开始时的所有进程,在循环结束时还存在”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










