You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:06:14