0

0

Python在Unix环境下监控子进程的内存与CPU时间使用教程

霞舞

霞舞

发布时间:2025-12-03 14:05:23

|

508人浏览过

|

来源于php中文网

原创

python在unix环境下监控子进程的内存与cpu时间使用教程

本教程详细阐述了如何在Unix系统下,利用Python的`subprocess`模块执行外部程序,并结合`resource`和`psutil`库精确监控其CPU时间(用户态与系统态)及内存使用情况。文章重点讲解了`resource.getrusage`的正确使用时机,以避免时间测量不准确的问题,并提供了基于进程ID的内存实时采样方法,确保对子进程性能进行全面而准确的评估。

在生物信息学工具开发、系统性能测试或任何需要执行外部命令并评估其效率的场景中,精确监控子进程的资源使用至关重要。本教程将指导您如何使用Python在Unix环境下实现这一目标,重点关注CPU时间(用户态和系统态)以及内存使用。

核心工具简介

我们将主要使用以下Python库:

  • subprocess: 用于启动新的应用程序或命令。
  • resource: 提供系统资源管理功能,包括获取进程的CPU时间。
  • psutil: 一个跨平台的库,用于检索正在运行的进程和系统利用率(CPU、内存、磁盘、网络等)的信息。
  • time: 用于在内存采样之间引入延迟。

监控CPU时间

resource模块提供了一个getrusage函数,可以用来获取进程及其子进程的资源使用情况。要准确测量由subprocess.Popen启动的子进程的CPU时间,关键在于getrusage的调用时机。

立即学习Python免费学习笔记(深入)”;

resource.getrusage的正确用法

resource.getrusage(resource.RUSAGE_CHILDREN)会返回所有已终止子进程所使用的资源总和。这意味着,如果您在子进程完成之前调用它来获取结束时的资源使用情况,它将不会包含当前仍在运行的子进程的数据。

常见错误: 在子进程启动后立即调用usage_end = resource.getrusage(resource.RUSAGE_CHILDREN),而子进程还在后台运行,会导致ru_utime和ru_stime显示为0,因为它只统计了在调用usage_end之前已经终止的子进程。

正确做法:

  1. 在启动子进程之前记录初始资源使用情况。
  2. 等待子进程完全终止。
  3. 在子进程终止后记录最终资源使用情况。

这样,最终的usage_end将包含由subprocess.Popen启动的子进程所消耗的全部CPU时间。

PathFinder
PathFinder

AI驱动的销售漏斗分析工具

下载

CPU时间类型:

  • ru_utime: 用户态CPU时间(user CPU time),表示进程在用户模式下执行指令所花费的时间。
  • ru_stime: 系统态CPU时间(system CPU time),表示进程在内核模式下执行系统调用所花费的时间。

示例代码(CPU时间部分)

import subprocess
import resource
import sys
import time

def measure_cpu_time(command_list):
    """
    测量子进程的CPU时间(用户态和系统态)。
    """
    print(f"Executing command: {' '.join(command_list)}")

    # 1. 启动前获取资源使用情况(包括已终止的子进程,通常为0)
    usage_start = resource.getrusage(resource.RUSAGE_CHILDREN)

    # 2. 启动子进程
    # subprocess.DEVNULL 避免子进程输出到控制台
    # subprocess.PIPE 捕获标准错误,以便在失败时打印
    process = subprocess.Popen(command_list, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, encoding='utf-8')

    # 3. 等待子进程完成
    # process.wait() 会阻塞直到子进程终止
    # 或者使用 process.poll() 循环等待,以便在循环中进行其他监控(如内存)
    process.wait()

    # 4. 子进程结束后获取资源使用情况
    usage_end = resource.getrusage(resource.RUSAGE_CHILDREN)

    # 5. 检查子进程退出码
    if process.returncode != 0:
        error_message = process.stderr.strip()
        sys.exit(f"FAILED: {' '.join(command_list)}\n{error_message}")

    # 6. 计算CPU时间
    cpu_time_user = usage_end.ru_utime - usage_start.ru_utime
    cpu_time_system = usage_end.ru_stime - usage_start.ru_stime

    print(f"User CPU Time: {cpu_time_user:.6f} seconds")
    print(f"System CPU Time: {cpu_time_system:.6f} seconds")
    return cpu_time_user, cpu_time_system

if __name__ == "__main__":
    # 示例:运行一个模拟耗时任务的命令
    # 例如:`sleep 5` 会等待5秒,但CPU时间很低
    # 更能体现CPU时间的命令可以是计算密集型任务,如 `dd if=/dev/zero of=/dev/null count=1000000 bs=1K`
    # 或者一个简单的Python脚本
    # command_to_run = ["sleep", "5"]
    command_to_run = ["python", "-c", "import time; sum(range(10**7)); time.sleep(1); sum(range(10**7))"]
    measure_cpu_time(command_to_run)

监控内存使用

psutil库提供了强大的功能来获取系统和进程的详细信息。要监控特定子进程的内存使用,我们需要获取其进程ID(PID),然后使用psutil.Process(pid)来查询该进程的内存信息。

psutil获取进程内存

psutil.Process(pid).memory_info()会返回一个包含多种内存指标的命名元组,其中:

  • rss (Resident Set Size): 进程实际使用的物理内存大小,是衡量进程内存消耗最常用的指标。
  • vms (Virtual Memory Size): 进程占用的虚拟内存大小。

为了实时监控,我们需要在子进程运行期间定期采样。

示例代码(内存部分)

import psutil
import time

def get_process_memory_usage(pid):
    """
    获取指定进程的RSS内存使用量(以GB为单位)。
    """
    try:
        process = psutil.Process(pid)
        return process.memory_info().rss / (1024.0 ** 3) # 转换为GB
    except psutil.NoSuchProcess:
        # 进程可能已经结束
        return 0.0
    except psutil.AccessDenied:
        # 权限不足,无法获取进程信息
        print(f"Warning: Access denied for process {pid}. Cannot get memory info.", file=sys.stderr)
        return 0.0

def monitor_memory_snapshots(process_obj, slice_in_seconds=1):
    """
    实时监控并收集子进程的内存快照。
    """
    memory_snapshots = []
    # 循环直到子进程结束
    while process_obj.poll() is None:
        mem_gb = get_process_memory_usage(process_obj.pid)
        if mem_gb > 0: # 只有当成功获取到内存信息时才记录
            memory_snapshots.append(mem_gb)
        time.sleep(slice_in_seconds)
    return memory_snapshots

# 注意:此函数不能单独运行,需要与subprocess结合
# 完整的集成示例将在下一节提供

重要提示: 原始问题中的get_memory_info函数调用的是psutil.virtual_memory(),这获取的是系统整体的内存使用情况,而非单个子进程。如果目标是监控子进程,务必使用psutil.Process(pid)来获取特定进程的内存信息。

整合CPU时间与内存监控

现在,我们将上述方法整合到一个完整的函数中,用于全面监控子进程的性能。

import sys
import os
import subprocess
import resource
import psutil
import time

def get_process_memory_usage(pid):
    """
    获取指定进程的RSS内存使用量(以GB为单位)。
    """
    try:
        process = psutil.Process(pid)
        return process.memory_info().rss / (1024.0 ** 3) # 转换为GB
    except (psutil.NoSuchProcess, psutil.AccessDenied):
        return 0.0

def monitor_subprocess_performance(command_list, report_file_path="performance_report.txt", slice_in_seconds=1):
    """
    监控子进程的CPU时间(用户态和系统态)及内存使用情况。
    """
    print(f"Executing command: {' '.join(command_list)}")

    # 1. 启动前获取资源使用情况
    usage_start = resource.getrusage(resource.RUSAGE_CHILDREN)

    # 2. 启动子进程
    process = subprocess.Popen(command_list, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, encoding='utf-8')

    # 3. 实时监控内存使用
    memory_snapshots = []
    # 循环直到子进程结束
    while process.poll() is None:
        mem_gb = get_process_memory_usage(process.pid)
        if mem_gb > 0:
            memory_snapshots.append(mem_gb)
        time.sleep(slice_in_seconds)

    # 4. 子进程结束后获取资源使用情况
    usage_end = resource.getrusage(resource.RUSAGE_CHILDREN)

    # 5. 检查子进程退出码
    if process.returncode != 0:
        error_message = process.stderr.strip()
        print(f"ERROR: Subprocess failed with code {process.returncode}:\n{error_message}", file=sys.stderr)
        sys.exit(f"FAILED: {' '.join(command_list)}\n{error_message}")

    # 6. 计算CPU时间
    cpu_time_user = usage_end.ru_utime - usage_start.ru_utime
    cpu_time_system = usage_end.ru_stime - usage_start.ru_stime

    # 7. 写入报告文件
    with open(report_file_path, "w") as f:
        f.write(f"Command: {' '.join(command_list)}\n")
        f.write(f"User CPU Time: {cpu_time_user:.6f} seconds\n")
        f.write(f"System CPU Time: {cpu_time_system:.6f} seconds\n")
        f.write(f"Peak RSS Memory: {max(memory_snapshots) if memory_snapshots else 0:.3f} GB\n")
        f.write(f"Memory Snapshots (RSS in GB): {memory_snapshots}\n")

    print(f"Monitoring complete. Report saved to {report_file_path}")
    print(f"User CPU Time: {cpu_time_user:.6f} seconds")
    print(f"System CPU Time: {cpu_time_system:.6f} seconds")
    print(f"Peak RSS Memory: {max(memory_snapshots) if memory_snapshots else 0:.3f} GB")
    print(f"Memory Snapshots (RSS in GB): {memory_snapshots}")

if __name__ == "__main__":
    # 示例:运行一个模拟耗时且有一定CPU和内存使用的命令
    # 这个Python脚本会进行一些计算并暂停,模拟真实工具的行为
    # 注意:在某些系统上,Python解释器本身也会消耗一定的CPU和内存
    command_to_run = [
        sys.executable, "-c",
        "import time, os; "
        "data = [i*i for i in range(10**6)]; "  # 模拟内存分配和一些计算
        "time.sleep(2); " # 暂停2秒
        "data2 = [x+1 for x in data]; " # 更多计算
        "time.sleep(1); " # 暂停1秒
        "print('Subprocess finished calculation and sleeping.');"
    ]

    # 您也可以替换为您的生物信息学工具命令,例如:
    # command_to_run = ["your_bioinformatics_tool", "--input", "file.fa", "--output", "result.txt"]

    monitor_subprocess_performance(command_to_run, "tool_performance_report.txt", slice_in_seconds=1)

    print("\n--- Testing a command with minimal CPU/memory (e.g., sleep) ---")
    monitor_subprocess_performance(["sleep", "3"], "sleep_performance_report.txt", slice_in_seconds=1)

注意事项与最佳实践

  1. resource.RUSAGE_CHILDREN的理解: 它统计的是所有已终止子进程的资源。因此,usage_end必须在目标子进程终止后获取,才能包含该子进程的资源使用情况。
  2. 内存采样频率: SLICE_IN_SECONDS决定了内存采样的频率。更小的值会提供更精细的内存使用曲线,但也会增加监控本身的开销。根据实际需求进行调整。
  3. 内存指标选择: psutil.Process(pid).memory_info().rss通常是衡量进程实际物理内存使用最相关的指标。vms(虚拟内存)可能包含未实际使用的内存。
  4. 错误处理: 务必检查子进程的returncode,并在非零时捕获并打印stderr中的错误信息,这对于调试外部工具至关重要。
  5. subprocess.Popen参数:
    • stdout=subprocess.DEVNULL: 将子进程的标准输出重定向到空设备,避免污染控制台。
    • stderr=subprocess.PIPE: 捕

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

182

2023.12.20

unix和linux的区别
unix和linux的区别

unix和linux的区别包括发展历史、开源性、发行版本、内核、文件系统、应用程序兼容性和用户界面等。本专题为大家提供unix和linux相关的文章、下载、课程内容,供大家免费下载体验。

392

2023.09.22

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

25

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

44

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

177

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

50

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

92

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

102

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

227

2026.03.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号