如何设置进度条并获取subprocess.Popen输出以优化FPGA构建日志展示
实现方案
依赖安装
仅需tqdm库即可完成需求,执行以下命令安装:
pip install tqdm
完整实现代码(优先旋转轮方案,无需预设步骤)
该方案无需提前匹配构建步骤,容错率极高,支持长时间无输出场景下的计时自动更新、旋转轮动效、最新构建行实时展示,构建结束后自动清理临时输出行:
from subprocess import Popen, PIPE, STDOUT import sys import time from tqdm import tqdm from itertools import cycle import threading def run_fpga_build(cmd): # 旋转轮字符序列 spinner = cycle(['|', '/', '-', '\\']) build_complete = threading.Event() latest_line = "" # 第一行进度条:展示旋转轮 + 运行时长 pbar = tqdm( total=0, bar_format="Running Build {desc} ({elapsed})", leave=True, dynamic_ncols=True, file=sys.stdout ) # 后台线程:实时更新旋转轮和计时,哪怕无构建输出 def update_spinner(): while not build_complete.is_set(): pbar.set_description_str(f"[{next(spinner)}]") pbar.refresh() time.sleep(0.2) spinner_thread = threading.Thread(target=update_spinner, daemon=True) spinner_thread.start() # 启动构建进程,合并stdout和stderr,行缓冲输出 p = Popen( cmd, shell=True, stdout=PIPE, stderr=STDOUT, text=True, bufsize=1, encoding="utf-8", errors="replace" ) # 实时读取构建输出 try: for line in iter(p.stdout.readline, ""): line = line.strip() if not line: continue latest_line = line # 动态更新第二行的最新构建输出,覆盖上一行 tqdm.write(f"\033[K{latest_line}", end="\r") finally: # 收尾处理 build_complete.set() spinner_thread.join() rc = p.wait() # 清除第二行的构建输出 tqdm.write("\033[K", end="\r") # 更新进度条为完成状态 pbar.bar_format = "Running Build [{}] ({elapsed})".format("."*30) pbar.refresh() pbar.close() # 打印换行,避免后续日志覆盖进度条 print() return rc # 调用示例 if __name__ == "__main__": print("INFO: starting build") return_code = run_fpga_build("你的FPGA构建脚本命令") print("<python continues logging stuff here>")
可选适配:分步进度条方案
如果已经梳理出完整的构建步骤列表,可将上述方案修改为分步进度条,仅需调整两处逻辑:
- 初始化tqdm时设置
total=len(lines_in_build_script) - 读取构建输出时匹配预设步骤,命中后调用
pbar.update(1)即可
效果说明
- 构建启动后完全符合需求示例效果:第一行展示旋转轮/进度条和实时运行时长,第二行展示最新构建输出
- 构建完成后自动清除第二行的临时输出,仅保留第一行的最终构建时长记录
- 后续Python日志会正常输出在进度条下方,不会被遮挡
内容的提问来源于stack exchange,提问作者nichollsg
相关产品推荐
相关产品推荐

