Python自定义ProgressBar无法同时显示多个,第二个覆盖第一个求解决方案
嘿,这个问题我太熟悉了!你遇到的问题根源在于\r这个回车符——它只会把光标移到当前行的开头,而不是新的一行,所以第二个进度条更新时直接覆盖了第一行的内容,最后就只能看到最后一个更新的进度条。
要实现多进度条同时显示,关键是用ANSI转义序列来控制光标位置,让每个进度条更新时回到自己对应的行,而不是都挤在同一行。下面给你两种解决方案:
方案一:快速修改现有代码
直接调整你的监控循环,手动控制光标位置,快速解决问题:
from pout_progressbar import ProgressBar import psutil import time import sys import os # Windows系统需要先启用ANSI转义支持(否则光标控制会失效) if os.name == 'nt': os.system("") bar1 = ProgressBar("CPU Usage", length=ProgressBar.standard, total=100) bar2 = ProgressBar("Memory Usage", length=ProgressBar.standard, total=100) # 先打印两个初始进度条,占好两行位置 bar1.update_bar(0) print() bar2.update_bar(0) print() while True: # 把光标向上移动2行,回到第一个进度条的行开头 sys.stdout.write("\033[2A") # 更新CPU进度条 bar1.update_bar(int(psutil.cpu_percent(interval=1))) # 换行到第二个进度条的行 sys.stdout.write("\n") # 更新内存进度条 bar2.update_bar(int(psutil.virtual_memory().percent)) # 强制刷新输出,确保内容立即显示 sys.stdout.flush() time.sleep(0.5)
代码说明:
\033[2A是ANSI转义码,意思是「光标向上移动2行」,这样每次循环都能回到第一个进度条的位置- 先打印初始的两行进度条,是为了预留好输出位置,避免后续更新时内容乱跑
- Windows下的
os.system("")是启用控制台的VT100支持,否则ANSI转义码会直接显示成乱码
方案二:封装进度条管理器(更优雅)
如果以后可能需要添加更多进度条,推荐写一个简单的管理器类,统一处理光标位置和更新逻辑,扩展性更好:
import sys import os # 先处理Windows的ANSI支持 if os.name == 'nt': os.system("") class ProgressBar(): full_size = 100 standard = 50 small = 25 def __init__(self, pretext, length=50, total=100): self.pretext = pretext self.length = length self.total = total def update_bar(self, fill_amount): real_fill_amount = int(self.length * fill_amount / self.total) # 保留\r用来覆盖当前行的旧内容 sys.stdout.write("\r%s |%s%s| %s" % (self.pretext, "█" * real_fill_amount, "░" * (self.length - real_fill_amount), str(fill_amount) + "%")) class ProgressBarManager: def __init__(self): self.bars = [] def add_bar(self, bar): """添加一个进度条,并打印初始状态""" self.bars.append(bar) bar.update_bar(0) print() def update_all(self, *fill_amounts): """批量更新所有进度条,按添加顺序对应填充值""" # 光标上移N行(N为进度条数量) sys.stdout.write(f"\033[{len(self.bars)}A") for bar, amount in zip(self.bars, fill_amounts): bar.update_bar(amount) sys.stdout.write("\n") sys.stdout.flush() # 使用示例 import psutil import time manager = ProgressBarManager() manager.add_bar(ProgressBar("CPU Usage", length=ProgressBar.standard, total=100)) manager.add_bar(ProgressBar("Memory Usage", length=ProgressBar.standard, total=100)) while True: cpu_percent = int(psutil.cpu_percent(interval=1)) mem_percent = int(psutil.virtual_memory().percent) manager.update_all(cpu_percent, mem_percent) time.sleep(0.5)
方案优势:
- 管理器自动跟踪所有进度条,不用手动计算光标移动行数
- 后续添加新进度条只需调用
manager.add_bar(),循环逻辑完全不用改 - 代码结构更清晰,维护成本更低
补充说明
如果你的终端不支持ANSI转义码(比如非常老旧的Windows cmd),也可以用「清空屏幕后重新打印所有进度条」的方式,但这种方式会有明显的闪烁感,体验远不如光标控制方案,所以优先推荐上面的ANSI实现。
内容的提问来源于stack exchange,提问作者Cubemation
相关产品推荐
相关产品推荐

