ZetCode

Python psutil

上次修改时间 2024年9月16日

在本文中,我们将展示如何检索有关进程和系统利用率的信息。

psutil 是一个 Python 模块,它提供了一个简单的接口来检索有关正在运行的进程、系统用户、网络、磁盘等的各种信息。 它是系统监控和管理任务的强大工具。

psutil.Process().info() 方法用于检索有关特定进程的详细信息。 它返回一个字典,其中包含进程的各种属性,例如:

在示例中,我们使用 argparse 模块来解析命令行参数。

列出内存使用情况

该示例列出内存使用量高于给定 MB 值的进程。

main.py
import psutil
import argparse


parser = argparse.ArgumentParser()
parser.add_argument('memory', help='memory value in MB')

args = parser.parse_args()

mem_limit = int(args.memory) * 1024 * 1024

p_it = psutil.process_iter(['name', 'memory_info'])

large_mem_ps = [{'pid': p.pid, 'name': p.info['name'], 'mem': p.info['memory_info'].rss}
                for p in p_it if p.info['memory_info'].rss > mem_limit]

for p in large_mem_ps:

    print(f'{p['pid']} {p['name']} {(p['mem'] / (1024 * 1024)):.2f}')

该程序接受一个位置参数:内存值,单位为 MB。

p_it = psutil.process_iter(['name', 'memory_info'])

process_iter 函数返回一个生成器,为所有正在运行的进程生成一个 Process 实例。 我们从生成的数据中挑选出进程的名称和 memory_info 属性。

large_mem_ps = [{'pid': p.pid, 'name': p.info['name'], 'mem': p.info['memory_info'].rss}
    for p in p_it if p.info['memory_info'].rss > mem_limit]

我们选择所有使用内存超过我们限制的进程。

for p in large_mem_ps:

    print(f'{p['pid']} {p['name']} {(p['mem'] / (1024 * 1024)):.2f}')

我们遍历列表并打印数据。

CPU 使用率

cpu_times 属性提供有关进程消耗的 CPU 时间的信息。

main.py
import psutil

processes = [
    {'pid': p.pid, 'name': p.info['name'],
        'sum_cpu_t': sum(p.info['cpu_times'])}
    for p in psutil.process_iter(['name', 'cpu_times'])
]

sorted_ps = sorted(processes, key=lambda p: p['sum_cpu_t'])

# print the last five
for e in sorted_ps[-5:]:
    print(f'pid: {e['pid']} name: {e['name']} cpu time: {e['sum_cpu_t']}')

该程序按 CPU 使用率列出前五个进程。

processes = [
    {'pid': p.pid, 'name': p.info['name'],
        'sum_cpu_t': sum(p.info['cpu_times'])}
    for p in psutil.process_iter(['name', 'cpu_times'])
]

我们获取一个进程列表,包括它们的进程 ID、名称和 CPU 使用率。

sorted_ps = sorted(processes, key=lambda p: p['sum_cpu_t'])

我们按其 CPU 时间总和(用户 + 系统)对进程进行排序。

# print the last five
for e in sorted_ps[-5:]:
    print(f'pid: {e['pid']} name: {e['name']} cpu time: {e['sum_cpu_t']}')

由于列表按升序排序,我们打印最后五个进程。

检查进程的日志文件

open_files 属性返回与该进程关联的文件描述符列表。 每个文件描述符表示为一个元组,包含以下信息:

main.py
import psutil

for p in psutil.process_iter(['name', 'open_files']):

    for file in p.info['open_files'] or []:

        if file.path.endswith('.log'):
            print(f"{p.pid:<5} {p.info['name']:<20} {file.path}")

该程序列出所有已打开日志文件的进程。

列出进程

以下脚本列出进程。 我们使用第三方 rich 库在控制台上的表格中显示输出。

main.py
import psutil
import argparse
from datetime import datetime
from rich import box
from rich.console import Console
from rich.table import Table
from datetime import date


def parse_arguments():
    parser = argparse.ArgumentParser()
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-a', '--all', action='store_true',
                        help='show all processes')
    group.add_argument('-n', '--name', help='show info about process name')
    args = parser.parse_args()
    return args.all, args.name


def list_process(name):
    now = f'{date.today()}'
    table = Table(title=f'Process', box=box.MINIMAL,
                    caption=now, caption_justify='left')
    table.add_column('id', style='cyan')
    table.add_column('process name', style='grey69')
    table.add_column('username')
    table.add_column('create time', style='blue')
    table.add_column('memory', style='green')

    process_count = 0

    for p in psutil.process_iter():

        if name in p.name().lower():
            ctime = datetime.fromtimestamp(p.create_time())
            memory_percent = p.memory_percent()
            table.add_row(f'{p.pid}', p.name(), p.username(),
                            ctime.isoformat(), f'{memory_percent:.2f}')
            process_count += 1

    if process_count > 0:

        console = Console()
        console.print(table, justify='center')
    else:

        print('no such process found')


def list_all_processes():

    now = f'{date.today()}'
    table = Table(title='Processes', box=box.MINIMAL,
                    caption=now, caption_justify='left')
    table.add_column('id', style='cyan')
    table.add_column('process name', style='grey69')

    pnames = []
    for p in psutil.process_iter():
        
        pnames.append(p.name())
        table.add_row(f'[bold]{p.pid}', f'[bold]{p.name()}')

    console = Console()
    console.print(table, justify='center')

    print(len(pnames), 'processes')
    print(len(set(pnames)), 'apps')


all_f, name = parse_arguments()

if all_f:
    list_all_processes()
elif name:
    list_process(name)    

该脚本接受两个选项:-a/-all 列出所有进程,而 -n/--name 显示有关特定进程的信息。 这些选项是互斥的。

来源

psutil 文档

在本文中,我们使用了 Python 中的谓词。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程