`psutil` 库:系统进程与资源监控的高级应用

各位观众,掌声欢迎!今天咱们不聊诗和远方,也不谈星辰大海,咱们就聊聊你电脑里的“内幕”——进程和资源,以及如何用Python的psutil库来当一回“电脑侦探”。

一、 什么是psutil? 为何我们要八卦它?

psutil(process and system utilities)是一个跨平台的 Python 库,它提供了一个统一的接口,让你能轻松访问系统运行的进程和系统利用率信息(CPU、内存、磁盘、网络等等)。

为啥要学它? 想象一下,你写了个程序,跑起来发现CPU风扇狂转,电脑卡得像老牛拉破车,这时候,你是不是想揪出那个“罪魁祸首”? 或者你想监控服务器资源,及时发现异常并报警,避免服务器崩溃? psutil就是你的神器!

二、 安装 psutil: 磨刀不误砍柴工

安装非常简单,打开你的命令行,输入:

pip install psutil

搞定!如果你用的是conda,那就:

conda install psutil

三、 psutil 的基本用法: 让我们来摸摸电脑的脉搏

  1. 获取进程列表:谁在偷偷摸摸干坏事?

    import psutil
    
    # 获取所有进程的pid
    pids = psutil.pids()
    print(f"当前运行的进程数量:{len(pids)}")
    
    # 遍历所有进程,打印进程名和pid
    for pid in pids:
       try:
           process = psutil.Process(pid)
           print(f"PID: {pid}, Process Name: {process.name()}")
       except psutil.NoSuchProcess:
           print(f"PID: {pid} (进程已结束)")
       except psutil.AccessDenied:
           print(f"PID: {pid} (权限不足)")
    

    这段代码会列出所有正在运行的进程,包括它们的PID(进程ID)和进程名。 注意,有些进程可能因为权限问题无法访问。

  2. 根据进程ID获取进程信息: 锁定目标,深入调查

    import psutil
    
    pid = 1  # 替换为你感兴趣的进程ID,比如系统的init进程
    try:
       process = psutil.Process(pid)
       print(f"进程名: {process.name()}")
       print(f"进程状态: {process.status()}")
       print(f"进程创建时间: {process.create_time()}")
       print(f"进程CPU占用率: {process.cpu_percent(interval=1)}%") # interval=1表示每隔1秒采样一次
       print(f"进程内存占用(RSS): {process.memory_info().rss / (1024 * 1024):.2f} MB")  # RSS 是实际使用的物理内存
       print(f"进程打开的文件: {process.open_files()}")
       print(f"进程使用的线程数: {process.num_threads()}")
    
    except psutil.NoSuchProcess:
       print(f"PID为 {pid} 的进程不存在")
    except psutil.AccessDenied:
       print(f"无法访问PID为 {pid} 的进程,权限不足")

    这段代码会获取指定PID的进程的详细信息,包括进程名、状态、CPU占用率、内存占用等。cpu_percent(interval=1) 里面的 interval=1 非常重要,它表示每隔1秒采样一次CPU占用率。如果不设置,第一次调用会返回0.0,第二次调用才会返回实际值。 内存占用方面,memory_info().rss 是Resident Set Size,表示进程实际使用的物理内存大小。

  3. CPU信息: 了解电脑的“心脏”

    import psutil
    
    # 获取CPU逻辑核心数
    cpu_count = psutil.cpu_count()
    print(f"CPU逻辑核心数: {cpu_count}")
    
    # 获取CPU物理核心数
    cpu_count_physical = psutil.cpu_count(logical=False)
    print(f"CPU物理核心数: {cpu_count_physical}")
    
    # 获取CPU利用率
    cpu_percent = psutil.cpu_percent(interval=1)
    print(f"CPU利用率: {cpu_percent}%")
    
    # 获取每个CPU核心的利用率
    cpu_percent_per_cpu = psutil.cpu_percent(interval=1, percpu=True)
    print(f"每个CPU核心的利用率: {cpu_percent_per_cpu}")
    
    # 获取CPU时间信息(用户态、系统态、空闲态等)
    cpu_times = psutil.cpu_times()
    print(f"CPU时间信息: {cpu_times}")
    
    # 获取CPU频率信息 (需要管理员权限)
    try:
       cpu_freq = psutil.cpu_freq()
       print(f"CPU频率: {cpu_freq}") # current, min, max
    except PermissionError:
       print("获取CPU频率需要管理员权限")

    这段代码会告诉你CPU有多少个核心,以及每个核心的利用率。cpu_count(logical=False) 获取的是物理核心数,cpu_count() 获取的是逻辑核心数(例如,如果你的CPU支持超线程,那么逻辑核心数是物理核心数的两倍)。 cpu_times 包含了CPU在不同状态下(用户态、系统态、空闲态等)运行的时间。 获取CPU频率可能需要管理员权限。

  4. 内存信息: 看看电脑的“记忆力”如何

    import psutil
    
    # 获取内存信息
    memory = psutil.virtual_memory()
    print(f"总内存: {memory.total / (1024 * 1024 * 1024):.2f} GB")
    print(f"可用内存: {memory.available / (1024 * 1024 * 1024):.2f} GB")
    print(f"已用内存: {memory.used / (1024 * 1024 * 1024):.2f} GB")
    print(f"内存使用率: {memory.percent}%")
    
    # 获取交换内存信息 (Swap)
    swap = psutil.swap_memory()
    print(f"交换内存总大小: {swap.total / (1024 * 1024 * 1024):.2f} GB")
    print(f"交换内存已用大小: {swap.used / (1024 * 1024 * 1024):.2f} GB")
    print(f"交换内存使用率: {swap.percent}%")

    这段代码会告诉你电脑的内存总量、可用内存、已用内存以及内存使用率。 还会告诉你交换内存(Swap)的使用情况。 交换内存是硬盘上的一块区域,当物理内存不够用时,操作系统会将一部分数据从物理内存转移到交换内存上。

  5. 磁盘信息: 了解你的“硬盘空间”

    import psutil
    
    # 获取磁盘分区信息
    partitions = psutil.disk_partitions()
    for partition in partitions:
       print(f"分区设备: {partition.device}")
       print(f"分区挂载点: {partition.mountpoint}")
       print(f"分区文件系统类型: {partition.fstype}")
    
       try:
           disk_usage = psutil.disk_usage(partition.mountpoint)
           print(f"  总空间: {disk_usage.total / (1024 * 1024 * 1024):.2f} GB")
           print(f"  已用空间: {disk_usage.used / (1024 * 1024 * 1024):.2f} GB")
           print(f"  可用空间: {disk_usage.free / (1024 * 1024 * 1024):.2f} GB")
           print(f"  使用率: {disk_usage.percent}%")
       except PermissionError:
           print("  没有权限访问该分区") # 有些系统分区可能需要管理员权限
    
    # 获取磁盘IO统计信息
    disk_io = psutil.disk_io_counters()
    print(f"磁盘读取次数: {disk_io.read_count}")
    print(f"磁盘写入次数: {disk_io.write_count}")
    print(f"磁盘读取字节数: {disk_io.read_bytes / (1024 * 1024):.2f} MB")
    print(f"磁盘写入字节数: {disk_io.write_bytes / (1024 * 1024):.2f} MB")

    这段代码会列出所有磁盘分区的信息,包括设备名、挂载点、文件系统类型、总空间、已用空间、可用空间以及使用率。 还会告诉你磁盘的IO统计信息,例如读取次数、写入次数、读取字节数和写入字节数。 注意,有些系统分区可能需要管理员权限才能访问。

  6. 网络信息: 掌握电脑的“通信状况”

    import psutil
    
    # 获取网络接口信息
    network_interfaces = psutil.net_if_addrs()
    for interface, addresses in network_interfaces.items():
       print(f"网络接口: {interface}")
       for address in addresses:
           print(f"  地址族: {address.family}")
           print(f"  地址: {address.address}")
           print(f"  网络掩码: {address.netmask}")
           print(f"  广播地址: {address.broadcast}")
    
    # 获取网络IO统计信息
    network_io = psutil.net_io_counters()
    print(f"接收字节数: {network_io.bytes_recv / (1024 * 1024):.2f} MB")
    print(f"发送字节数: {network_io.bytes_sent / (1024 * 1024):.2f} MB")
    print(f"接收包数: {network_io.packets_recv}")
    print(f"发送包数: {network_io.packets_sent}")

    这段代码会列出所有网络接口的信息,包括接口名、IP地址、网络掩码、广播地址。 还会告诉你网络的IO统计信息,例如接收字节数、发送字节数、接收包数和发送包数。

四、 psutil 的高级用法: 成为真正的电脑侦探

  1. 实时监控进程资源占用:揪出“资源大户”

    import psutil
    import time
    
    def monitor_process(pid, interval=1):
       """
       实时监控进程的CPU和内存占用率
       :param pid: 进程ID
       :param interval: 采样间隔,单位秒
       """
       try:
           process = psutil.Process(pid)
           while True:
               cpu_percent = process.cpu_percent(interval=interval)
               memory_percent = process.memory_percent()
               print(f"PID: {pid}, CPU: {cpu_percent}%, Memory: {memory_percent}%")
               time.sleep(interval)
       except psutil.NoSuchProcess:
           print(f"PID为 {pid} 的进程不存在")
       except KeyboardInterrupt:
           print("监控结束")
    
    if __name__ == '__main__':
       pid_to_monitor = int(input("请输入要监控的进程PID: "))
       monitor_process(pid_to_monitor)

    这段代码可以实时监控指定进程的CPU和内存占用率。 你可以通过输入进程ID来指定要监控的进程。 程序会一直运行,直到你按下Ctrl+C来停止监控。

  2. 进程管理: “生杀大权”在手

    import psutil
    
    def kill_process(pid):
       """
       结束指定PID的进程
       :param pid: 进程ID
       """
       try:
           process = psutil.Process(pid)
           process.kill()
           print(f"已成功结束PID为 {pid} 的进程")
       except psutil.NoSuchProcess:
           print(f"PID为 {pid} 的进程不存在")
       except psutil.AccessDenied:
           print(f"无法结束PID为 {pid} 的进程,权限不足")
    
    def suspend_process(pid):
       """
       暂停指定PID的进程
       :param pid: 进程ID
       """
       try:
           process = psutil.Process(pid)
           process.suspend()
           print(f"已成功暂停PID为 {pid} 的进程")
       except psutil.NoSuchProcess:
           print(f"PID为 {pid} 的进程不存在")
       except psutil.AccessDenied:
           print(f"无法暂停PID为 {pid} 的进程,权限不足")
    
    def resume_process(pid):
       """
       恢复指定PID的进程
       :param pid: 进程ID
       """
       try:
           process = psutil.Process(pid)
           process.resume()
           print(f"已成功恢复PID为 {pid} 的进程")
       except psutil.NoSuchProcess:
           print(f"PID为 {pid} 的进程不存在")
       except psutil.AccessDenied:
           print(f"无法恢复PID为 {pid} 的进程,权限不足")
    
    if __name__ == '__main__':
       pid_to_manage = int(input("请输入要管理的进程PID: "))
       action = input("请输入要执行的操作 (kill/suspend/resume): ")
    
       if action == "kill":
           kill_process(pid_to_manage)
       elif action == "suspend":
           suspend_process(pid_to_manage)
       elif action == "resume":
           resume_process(pid_to_manage)
       else:
           print("无效的操作")

    这段代码可以结束、暂停和恢复指定PID的进程。 注意,结束或暂停一些系统进程可能会导致系统不稳定,请谨慎使用。 同样,你需要管理员权限才能管理一些进程。

  3. 系统事件监控: “风吹草动”尽在掌握

    import psutil
    
    def monitor_system_events():
       """
       监控系统事件,例如进程创建和结束
       """
       try:
           for event in psutil.process_iter(['pid', 'name', 'status']):
               print(f"PID: {event.info['pid']}, Name: {event.info['name']}, Status: {event.info['status']}")
       except psutil.NoSuchProcess:
           print("进程已结束")
       except psutil.AccessDenied:
           print("权限不足")
    
    if __name__ == '__main__':
       monitor_system_events()

    这段代码使用psutil.process_iter()迭代器来监控系统中所有进程的状态。 你可以根据进程的状态来判断进程是创建、运行还是结束。 这个示例只是简单地打印进程的信息,你可以根据自己的需求来定制监控逻辑,例如记录日志、发送报警等。 需要注意的是,process_iter()在大量进程的情况下可能会比较耗费资源,请根据实际情况进行优化。

五、 实战案例: 用 psutil 打造一个简单的系统监控工具

下面我们来用psutil打造一个简单的系统监控工具,可以实时显示CPU、内存、磁盘和网络的利用率。

import psutil
import time
import os

def clear_screen():
    """
    清空屏幕
    """
    os.system('cls' if os.name == 'nt' else 'clear')

def get_cpu_usage():
    """
    获取CPU利用率
    """
    return psutil.cpu_percent(interval=1)

def get_memory_usage():
    """
    获取内存利用率
    """
    memory = psutil.virtual_memory()
    return memory.percent

def get_disk_usage():
    """
    获取磁盘利用率 (这里只取第一个分区)
    """
    try:
        partitions = psutil.disk_partitions()
        if partitions:
            disk_usage = psutil.disk_usage(partitions[0].mountpoint)
            return disk_usage.percent
        else:
            return 0
    except PermissionError:
        return "N/A (权限不足)"

def get_network_usage():
    """
    获取网络利用率 (这里只取发送和接收字节数之和)
    """
    network_io = psutil.net_io_counters()
    return network_io.bytes_sent + network_io.bytes_recv

def display_system_info():
    """
    显示系统信息
    """
    cpu_usage = get_cpu_usage()
    memory_usage = get_memory_usage()
    disk_usage = get_disk_usage()
    network_usage = get_network_usage()

    print("系统资源监控:")
    print(f"CPU利用率: {cpu_usage}%")
    print(f"内存利用率: {memory_usage}%")
    print(f"磁盘利用率: {disk_usage}%")
    print(f"网络流量: {network_usage / (1024 * 1024):.2f} MB")

if __name__ == '__main__':
    try:
        while True:
            clear_screen()
            display_system_info()
            time.sleep(1)
    except KeyboardInterrupt:
        print("监控结束")

这段代码会每隔1秒刷新一次屏幕,显示CPU、内存、磁盘和网络的利用率。 你可以根据自己的需求来扩展这个工具,例如添加进程监控、报警功能等。

六、 注意事项: 当“侦探”也要讲规矩

  • 权限问题: 有些信息需要管理员权限才能访问,例如CPU频率、某些进程的信息。
  • 性能问题: 频繁调用psutil的函数可能会影响系统性能,特别是process_iter()cpu_percent(interval=0)。 建议设置合适的采样间隔,避免过度占用资源。
  • 跨平台差异: 虽然psutil是跨平台的,但不同操作系统上的某些细节可能会有所不同。 建议在不同平台上进行测试,确保代码的兼容性。
  • 异常处理: 在使用psutil时,要考虑到各种异常情况,例如进程不存在、权限不足等。 使用try...except语句来捕获这些异常,避免程序崩溃。

七、 总结: psutil,你值得拥有!

psutil是一个非常强大的Python库,可以帮助你轻松访问系统运行的进程和资源信息。 无论是监控系统性能、排查程序问题,还是进行系统管理,psutil都是你的得力助手。 希望通过今天的讲解,你已经对psutil有了更深入的了解,并能将其应用到实际项目中。

最后,记住一句至理名言: “代码千万行,注释第一行。 规范注释好,debug没烦恼。” 祝大家编程愉快!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注