如何用Python实时获取PresentMon的游戏FPS输出?
解决Python实时捕获PresentMon FPS输出的问题
问题根源
你的代码存在几个关键问题导致无法实时获取PresentMon的FPS输出:
- 未添加
-r参数:PresentMon默认不会输出实时FPS行,必须通过-r启用实时监控输出。 - 使用
CREATE_NEW_CONSOLE:该参数会让PresentMon在独立控制台运行,其stdout/stderr不会关联到Python的管道,导致无法捕获输出。 - 一次性读取
stdout:p.stdout.read()会等待进程结束后读取全部输出,无法实现实时获取。 - 输出缓冲:默认的管道缓冲会延迟输出内容的传递,导致无法实时拿到数据。
修复后的代码
import subprocess import re def stop_PresentMon(): # 静默终止现有进程,避免输出干扰 subprocess.run(['PresentMon64.exe', '-terminate_existing'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=False) def start_presentmon(pid): # 添加 -r 参数启用实时输出,关闭缓冲,合并stdout/stderr command = ['PresentMon64.exe', '-process_id', str(pid), '-r'] p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0, # 无缓冲,实时输出 text=True, # 自动处理编码,返回字符串 encoding='utf-8') # 正则表达式匹配FPS数值(匹配类似 "45.4/47.1 fps" 中的数值) fps_pattern = re.compile(r'\((\d+\.\d+)/(\d+\.\d+) fps\)') try: # 逐行读取实时输出 for line in iter(p.stdout.readline, ''): line = line.strip() if not line: continue # 打印原始输出(可选) print(line) # 提取FPS数值 match = fps_pattern.search(line) if match: cpu_fps = float(match.group(1)) display_fps = float(match.group(2)) print(f"提取到FPS: CPU={cpu_fps}, Display={display_fps}") except KeyboardInterrupt: # 捕获中断信号,优雅终止PresentMon p.terminate() p.wait() if __name__ == "__main__": pid = 12512 stop_PresentMon() start_presentmon(pid)
关键修改说明
- 添加
-r参数:启用PresentMon的实时监控模式,输出你需要的FPS行内容。 - 移除
CREATE_NEW_CONSOLE:让PresentMon的输出直接流入Python的管道。 bufsize=0:关闭输出缓冲,确保每一行输出都能立即被Python读取。iter(p.stdout.readline, ''):逐行读取输出,实现实时获取,避免等待进程结束。- 合并
stdout和stderr:确保不会遗漏任何输出信息(比如错误提示或状态信息)。 - 正则提取FPS:通过正则表达式从输出行中精准提取CPU/Display FPS数值,方便后续处理。
额外注意事项
- 确保PresentMon64.exe在Python的运行路径中,或者使用完整路径调用(比如
'C:/Tools/PresentMon64.exe')。 - 如果遇到编码错误,可以尝试调整
encoding参数(比如'gbk'),适配你的系统编码。 - 终止程序时,使用
Ctrl+C会自动触发PresentMon的终止逻辑,避免进程残留。
内容的提问来源于stack exchange,提问作者Владислав Фесик
相关产品推荐
相关产品推荐

