Python中如何实现多行输出时的原地刷新?

单行原地刷新方法挺多的,多行原地刷新要这么做?

类似这样的多行
±-------±-----------------------------±-----------±-----------------+
| 代码 | 名称 | 估算涨幅 | 更新时间 |
|--------±-----------------------------±-----------±-----------------|
| 110022 | 易方达消费行业 | -0.61% | 2018-07-20 10:39 |
| 260108 | 景顺长城新兴成长混合 | -0.03% | 2018-07-20 10:39 |
| 000220 | 富国医疗保健行业混合 | +0.19% | 2018-07-20 10:39 |
| 003095 | 中欧医疗健康混合 A | +0.07% | 2018-07-20 10:39 |
| 161725 | 招商中证白酒指数分级 | -0.44% | 2018-07-20 10:39 |
| 160222 | 国泰国证食品饮料行业指数分级 | -0.20% | 2018-07-20 10:39 |
| 270002 | 广发稳健增长 | +0.08% | 2018-07-20 10:39 |
| 519690 | 交银稳健配置混合 A | -0.04% | 2018-07-20 10:38 |
| 270042 | 广发纳斯达克 100 指数 | -0.48% | 2018-07-20 04:00 |
| 001092 | 广发生物科技指数(QDII) | -0.48% | 2018-07-20 04:00 |
| 160213 | 国泰纳斯达克 100 指数 | -0.45% | 2018-07-20 04:00 |
| 000369 | 广发全球医疗保健现钞 | -0.34% | 2018-07-20 04:00 |
±-------±-----------------------------±-----------±-----------------+
Python中如何实现多行输出时的原地刷新?


25 回复

在Python里要实现多行输出的原地刷新,核心是用\r回车符和sys.stdoutwrite()flush(),或者直接用print(..., end='\r', flush=True)。但\r只会回到行首,要刷新多行就得用更底层的控制,比如curses库(但Windows支持有限)或者不断重写多行内容。

一个更通用的方法是利用ANSI转义序列(大多数现代终端都支持),先清除屏幕或从当前光标位置清除到屏幕末尾,然后重新打印所有行。这里给你一个清晰可运行的例子:

import time
import sys

def clear_lines(n=1):
    """将光标上移n行并清除这些行的内容"""
    for _ in range(n):
        sys.stdout.write('\033[F')  # 光标上移一行
        sys.stdout.write('\033[K')  # 清除该行

def multi_line_refresh():
    lines = [
        "进度条1: [>         ] 0%",
        "进度条2: [>         ] 0%",
        "状态: 初始化..."
    ]
    # 首次打印
    for line in lines:
        print(line)
    
    for i in range(1, 11):
        time.sleep(0.5)  # 模拟耗时操作
        # 1. 清除之前打印的3行
        clear_lines(3)
        # 2. 更新内容
        lines = [
            f"进度条1: [{'='*i}{'>' if i<10 else '='}         ] {i*10}%",
            f"进度条2: [{'='*i}{'>' if i<10 else '='}         ] {i*10}%",
            f"状态: 处理中... ({i}/10)"
        ]
        # 3. 重新打印
        for line in lines:
            print(line)

if __name__ == "__main__":
    multi_line_refresh()
    print("\n处理完成!")

原理说明:

  1. \033[F 是ANSI转义序列,作用是将光标移动到上一行的行首。
  2. \033[K 是清除从光标位置到行尾的内容。
  3. 我们通过clear_lines(n)函数组合这两个序列,先上移光标,再清除该行,循环n次来清除之前输出的n行。
  4. 在循环中,先清除旧内容,再生成并打印新的多行内容,视觉上就实现了多行同时原地刷新。

注意:

  • 这个方法在Windows的CMD和PowerShell上可能不工作,因为它们默认不支持ANSI序列。但在Windows Terminal、VS Code终端、Linux/macOS的终端里都能正常跑。
  • 如果你在Windows且必须用CMD,可以考虑用os.system('cls')全清屏再重打,但那就不是“原地”刷新了,会闪屏。

一句话总结:用ANSI转义序列\033[F\033[K组合来上移光标并清除行,是最实用的多行原地刷新方法。

import sys
import time

for i in range(10):
print(’\r{}’.format(i), end=’’)
sys.stdout.flush()
time.sleep(0.1)
print()

import sys
import time

for i in range(10):
[缩进] print(’\r{}’.format(i), end=’’)
[缩进] sys.stdout.flush()
[缩进] time.sleep(0.1)
print()

清屏后再打印就可以了

我用的 Windows 系统,貌似没有这个模块吧

清屏在打印屏幕容易闪烁,能不能直接覆盖?

print(’/r666’)

多行刷新 windows 下暂时不知道怎么实现

单行的话 windows 下#3 那个方法 line5 的 print 函数换成 sys.stdout.write 就可以了

这个项目貌似也不支持 Windows

\r了解一下?

退格键了解下

那效果跟清屏命令类似吧,也会出现闪烁,不是覆盖的那种效果

这个只能跳到最后一行的开后,不能跳到第一行的开头,对多行不起作用

Windows 的话有 API 设置控制台光标位置,设置后再 print 就可以覆盖了。

#16 试试这个

<br>import time<br>import sys<br>count = 1<br>while count &lt; 99:<br> sys.stdout.write("current {0}%\r".format(count))<br> sys.stdout.flush()<br> count += 1<br> time.sleep(0.5)<br>

https://github.com/Yinzo/reprint 应该是符合你的要求的,配合 prettytable 搞一搞,linux 没问题,windows 不知道

Windows 下面我见过两种比较简单的解决方案
gist.github.com/littlecodersh/2ab4d88070eb16bf9f2b26f7cbc16ad0

库 ncursers ?

搭车问一句,mac 下中英文混合的这种表格,比如 prettytable,你们怎么搞对齐的?

ansi 控制码,VT100 了解下

回到顶部