
本文旨在指导如何在Unix环境下使用Python精确监控子进程的内存占用和CPU时间。我们将探讨使用`subprocess`启动进程,结合`resource`库测量CPU时间,以及`psutil`库跟踪内存使用的最佳实践。重点解决`resource.getrusage`在不当位置调用导致时间统计为零的常见问题,并提供一个结构清晰、功能完整的示例代码。
在数据分析、科学计算或系统管理等领域,经常需要执行外部命令或第三方工具作为子进程。为了评估这些工具的性能、优化资源分配或进行基准测试,精确监控子进程的资源使用情况至关重要。本教程将详细介绍如何利用Python的subprocess、resource和psutil库,在Unix系统上有效地测量子进程的内存占用和CPU时间。
在使用resource.getrusage(resource.RUSAGE_CHILDREN)来测量子进程的CPU时间时,一个常见的错误是将结束测量点放置在子进程完成之前。resource.RUSAGE_CHILDREN设计用于统计已终止子进程的资源使用情况。这意味着,如果在子进程仍在运行时调用usage_end = resource.getrusage(resource.RUSAGE_CHILDREN),它将只报告在当前进程生命周期中已经终止的子进程所消耗的资源,而不会包含当前正在运行的子进程。
因此,为了准确获取目标子进程的CPU时间,必须在子进程完全终止并被父进程回收资源后,再调用resource.getrusage(resource.RUSAGE_CHILDREN)。
立即学习“Python免费学习笔记(深入)”;
以下是一个结合了subprocess、resource和psutil的完整示例,展示了如何正确地监控子进程的内存和CPU时间。
Text Mark
处理文本内容的AI助手
113
查看详情
import sys
import os
import subprocess
import resource
import psutil
import time
import datetime
def get_process_memory_info(pid):
"""
获取指定PID进程的内存使用信息(常驻内存RSS)。
如果进程不存在,返回None。
"""
try:
process = psutil.Process(pid)
# memory_info().rss 是常驻内存集大小 (Resident Set Size),以字节为单位
# 转换为GB
return process.memory_info().rss / (1024.0 ** 3)
except psutil.NoSuchProcess:
return None
except Exception as e:
print(f"获取进程 {pid} 内存信息失败: {e}", file=sys.stderr)
return None
def monitor_subprocess_resources(cmd_list, report_file_path, slice_in_seconds=1):
"""
监控子进程的CPU时间(用户态和系统态)和内存使用。
Args:
cmd_list (list): 包含命令及其参数的列表,例如 ['bioinformatics_tool', 'arg1', 'arg2']。
report_file_path (str): 报告文件路径,用于保存监控结果。
slice_in_seconds (int): 内存采样间隔时间(秒)。
"""
print(f"开始监控命令: {' '.join(cmd_list)}")
print(f"报告将写入: {report_file_path}")
# 记录开始时间,用于计算总运行时间(可选,与resource模块无关)
start_time_wall = time.time()
# 在子进程启动前获取初始资源使用情况
# resource.RUSAGE_CHILDREN 统计所有已终止子进程的资源
# 如果父进程之前没有其他子进程,这里通常是0
usage_start = resource.getrusage(resource.RUSAGE_CHILDREN)
# 启动子进程
# stdout=subprocess.DEVNULL 将标准输出重定向到空设备
# stderr=subprocess.PIPE 捕获标准错误输出
try:
process = subprocess.Popen(
cmd_list,
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
encoding='utf-8'
)
pid = process.pid
print(f"子进程PID: {pid}")
except FileNotFoundError:
print(f"错误:命令 '{cmd_list[0]}' 未找到。", file=sys.stderr)
return
except Exception as e:
print(f"启动子进程失败: {e}", file=sys.stderr)
return
# 存储内存采样结果
memory_samples = []
# 循环检查子进程状态并采样内存
while process.poll() is None:
current_memory_gb = get_process_memory_info(pid)
if current_memory_gb is
not None:
memory_samples.append(current_memory_gb)
time.sleep(slice_in_seconds)
# 子进程已终止,检查返回码
if process.returncode != 0:
error_output = process.stderr.read()
print(f"子进程执行失败,返回码: {process.returncode}", file=sys.stderr)
print(f"错误输出:\n{error_output}", file=sys.stderr)
sys.exit(f"FAILED: {' '.join(cmd_list)}\n{error_output}")
# 在子进程终止后获取最终资源使用情况
# 此时 resource.RUSAGE_CHILDREN 会包含刚刚终止的子进程的资源
usage_end = resource.getrusage(resource.RUSAGE_CHILDREN)
end_time_wall = time.time() # 记录结束时间
# 计算CPU时间
cpu_time_user = usage_end.ru_utime - usage_start.ru_utime
cpu_time_system = usage_end.ru_stime - usage_start.ru_stime
total_cpu_time = cpu_time_user + cpu_time_system
wall_clock_time = end_time_wall - start_time_wall
# 写入报告文件
with open(report_file_path, "w") as outrepfp:
outrepfp.write(f"Command: {' '.join(cmd_list)}\n")
outrepfp.write(f"Wall Clock Time: {wall_clock_time:.4f} seconds\n")
outrepfp.write(f"User CPU Time: {cpu_time_user:.4f} seconds\n")
outrepfp.write(f"System CPU Time: {cpu_time_system:.4f} seconds\n")
outrepfp.write(f"Total CPU Time: {total_cpu_time:.4f} seconds\n")
outrepfp.write(f"Memory Usage (GB) Samples: {memory_samples}\n")
if memory_samples:
outrepfp.write(f"Peak Memory (GB): {max(memory_samples):.4f}\n")
else:
outrepfp.write("Peak Memory (GB): N/A (no memory samples collected)\n")
print("\n监控完成,报告已生成。")
print(f"Wall Clock Time: {wall_clock_time:.4f} seconds")
print(f"User CPU Time: {cpu_time_user:.4f} seconds")
print(f"System CPU Time: {cpu_time_system:.4f} seconds")
print(f"Peak Memory (GB): {max(memory_samples) if memory_samples else 'N/A'}")
# --- 示例用法 ---
if __name__ == "__main__":
# 模拟一个长时间运行的命令
# 例如:'sleep 5' 会运行5秒
# 对于生物信息学工具,替换为你的实际命令
# 例如: bioinformatics_tool = "bwa"
# setups = "mem -t 4"
# resultdir = "output.sam"
# inputs = "input.fastq"
# cmd = [bioinformatics_tool, setups, "--tblout", resultdir, inputs]
# 示例1: 简单的sleep命令
print("--- 运行示例 1: sleep 5 ---")
mock_command_sleep = ['sleep', '5'] # 模拟一个运行5秒的命令
report_file_sleep = "report_sleep.txt"
monitor_subprocess_resources(mock_command_sleep, report_file_sleep, slice_in_seconds=1)
print("-" * 30)
# 示例2: 模拟一个简单的Python脚本作为子进程
# 创建一个模拟的Python脚本文件
with open("mock_script.py", "w") as f:
f.write("""
import time
import sys
import os
print("Mock script started.")
# 模拟内存使用增长 (并非实际内存分配,仅为示例)
data = []
for i in range(10):
time.sleep(0.5)
# 实际内存使用可以通过分配大对象来模拟,这里仅为示意
# data.append(os.urandom(1024 * 1024)) # 每次增加1MB,但会很快耗尽内存
print(f"Mock script working... {i+1}s")
sys.stdout.flush() # 确保输出及时显示
print("Mock script finished.")
""")
print("--- 运行示例 2: mock_script.py ---")
mock_command_python_script = [sys.executable, 'mock_script.py']
report_file_python_script = "report_python_script.txt"
monitor_subprocess_resources(mock_command_python_script, report_file_python_script, slice_in_seconds=0.5)
os.remove("mock_script.py") # 清理模拟脚本
print("-" * 30)get_process_memory_info(pid) 函数:
monitor_subprocess_resources 函数:
平台兼容性:
采样频率: slice_in_seconds参数决定了内存采样的频率。更小的值会提供更精细的内存使用曲线,但也会增加父进程的CPU开销。需要根据实际需求和子进程的运行特性进行权衡。
通过本教程,我们学习了如何在Python中利用subprocess、resource和psutil库,在Unix环境下对子进程的内存和CPU时间进行精确监控。核心要点在于理解resource.getrusage(resource.RUSAGE_CHILDREN)的工作机制,确保在子进程终止后才进行最终的资源统计,以避免时间统计为零的常见问题。结合psutil的实时内存采样,我们可以获得子进程运行期间全面的性能数据,这对于性能分析和优化具有重要意义。
以上就是Python子进程资源监控:精确测量内存与CPU时间的详细内容,更多请关注其它相关文章!
# python
# windows
# linux
# 的是
# 周到的福州Seo排名
# 兖州营销推广效果好
# 唐山网站建设及优化
# 集大
# 就会
# 这是
# 是一个
# 都是
# 为零
# 第三方
# app
# 字节
# 工具
# mac
# ai
# unix
# macos
# win
# 仅为
# 错误信息
# seo内容优化原创
# 7月地产营销推广活动
# 汝南推广网站多少钱一个
# 博罗广告网站建设
# 账号包含营销推广信息吗
# 嘉善首页推广营销
# 阿里云seo待遇
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
京东快递物流信息不更新怎么办_物流停滞原因与处理方法
OPPO A3 WiFi频繁断开怎么办 OPPO A3网络优化技巧
处理含命名空间的XML文件 Power Query中的高级技巧
之了课堂app做题入口
Yandex世界探索 最新官方免登录入口全知道
12306售票时间最新规定 | 网上订票和车站窗口时间一样吗
多闪电脑版下载_多闪PC端模拟器使用
Golang如何测试结构体方法_Golang reflect方法测试与调用技巧
C#解析来自网络的XML流数据 实时错误处理与重试机制
Lar*el Eloquent:高效删除多对多关系中无关联子记录的父模型
在Django单元测试中优雅处理信号:基于环境的条件执行策略
如何在vscode中关闭it环境
飞飞漫画漫画阅读官网_飞飞漫画漫画阅读官网进入阅读
Firefox OS应用开发:解决XMLHttpRequest跨域请求阻塞问题
《幻兽帕鲁》手游帕鲁捕捉技巧分享
word页码灰色不能用如何解决
QQ阅读小说搜索入口地址_QQ阅读小说搜索入口地址搜索在线阅读
深入理解Python对象引用与链表属性赋值
优化 WooCommerce 产品价格显示与自定义短代码集成
邦丰播放器频道搜索设置
《原神》月之一版本新增书籍一览
《飞猪旅行》购买汽车票方法
批改网官网首页登录 批改网学生用户登录入口
win11如何运行chkdsk命令 Win11检查和修复磁盘逻辑错误教程【修复】
如何在mysql中设计餐饮点餐系统_mysql点餐系统项目实战
win11如何诊断DirectX问题 Win11运行dxdiag工具排查显卡故障【排错】
雨课堂官网在线登录 网页版雨课堂登录链接
《微信》视频号原创声明开启方法
《长生:天机降世》火塔小怪大全
小红书如何引流到私信?引流到私信有用吗?
《暗黑破坏神4》国服回归送狂欢礼包 价值6916元
Google Drive API服务器端访问指南:服务账户认证详解
Lar*el Dusk 测试中管理浏览器权限:以剪贴板访问为例
Sublime怎么自动添加CSS前缀_Sublime安装Autoprefixer插件
《360浏览器》设置摄像头权限方法
Chart.js 教程:自定义插件实现图表与图例间距调整
性能与资源监视器快捷打开
我的世界官方网址入口 我的世界游戏主页直达入口
《百果园》充值余额方法
猫眼电影app如何设置电影上映提醒_猫眼电影上映提醒设置教程
智云Q3和Q2有什么升级_智云Q3与Q2手持云台功能与性能对比分析
Lar*el如何创建自定义的辅助函数(Helpers)_Lar*el全局函数定义与加载方法
《大周列国志》皇帝律令功能介绍
word表格如何按某一列内容进行排序_Word表格按列排序方法
CSS绝对定位与溢出控制:实现背景元素局部显示不触发滚动条
Dagster资产间数据传递与用户配置管理教程
被称为海蜈蚣的海洋动物是
苹果手机如何清理系统缓存数据 iPhone非越狱清理垃圾文件的技巧【系统优化】
《战地6》反作弊已成功拦截240万次作弊 发售第一周98%比赛没有作弊
win11怎么更改账户类型 Win11标准用户和管理员权限切换【教程】
2025-12-14
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。