Python监控进程资源使用方法
大家好,今天本人给大家带来文章《Python监控子进程内存与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的调用时机。
resource.getrusage的正确用法
resource.getrusage(resource.RUSAGE_CHILDREN)会返回所有已终止子进程所使用的资源总和。这意味着,如果您在子进程完成之前调用它来获取结束时的资源使用情况,它将不会包含当前仍在运行的子进程的数据。
常见错误: 在子进程启动后立即调用usage_end = resource.getrusage(resource.RUSAGE_CHILDREN),而子进程还在后台运行,会导致ru_utime和ru_stime显示为0,因为它只统计了在调用usage_end之前已经终止的子进程。
正确做法:
- 在启动子进程之前记录初始资源使用情况。
- 等待子进程完全终止。
- 在子进程终止后记录最终资源使用情况。
这样,最终的usage_end将包含由subprocess.Popen启动的子进程所消耗的全部CPU时间。
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)注意事项与最佳实践
- resource.RUSAGE_CHILDREN的理解: 它统计的是所有已终止子进程的资源。因此,usage_end必须在目标子进程终止后获取,才能包含该子进程的资源使用情况。
- 内存采样频率: SLICE_IN_SECONDS决定了内存采样的频率。更小的值会提供更精细的内存使用曲线,但也会增加监控本身的开销。根据实际需求进行调整。
- 内存指标选择: psutil.Process(pid).memory_info().rss通常是衡量进程实际物理内存使用最相关的指标。vms(虚拟内存)可能包含未实际使用的内存。
- 错误处理: 务必检查子进程的returncode,并在非零时捕获并打印stderr中的错误信息,这对于调试外部工具至关重要。
- subprocess.Popen参数:
- stdout=subprocess.DEVNULL: 将子进程的标准输出重定向到空设备,避免污染控制台。
- stderr=subprocess.PIPE: 捕
到这里,我们也就讲完了《Python监控进程资源使用方法》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!
PHP数组删除指定值的技巧与方法
- 上一篇
- PHP数组删除指定值的技巧与方法
- 下一篇
- 追书大全官网地址2025最新版更新
-
- 文章 · python教程 | 10分钟前 |
- Python多版本共存与虚拟环境使用技巧
- 467浏览 收藏
-
- 文章 · python教程 | 38分钟前 |
- Python3字典copy方法详解
- 216浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- Python忽略文件未找到错误的简洁方法
- 287浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- Scrapy-Redis分布式爬虫实战解析
- 207浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python爬虫多级解析技巧与优化方法
- 299浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python办公系统第264讲:核心原理与实战解析
- 122浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python导入机制详解与原理剖析
- 255浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- 自动化脚本调优模型全流程详解
- 439浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python爬虫项目上线注意事项
- 396浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- {%with%}标签变量作用域与累加使用详解
- 472浏览 收藏
-
- 文章 · python教程 | 3小时前 | Python函数
- Python生成器实现协程详解教程
- 315浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Python中的反向传播算法详解
- 322浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3485次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3709次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3710次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4855次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 4083次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览

