文本环绕时清除终端中的最后一行

时间:2017-11-08 00:58:44

标签: python terminal stdout ansi

在我的python程序中,我想在很长的循环中打印进度。我想输出特定信息,如完成百分比等...,但我不希望所有这些输出占据整个屏幕。

理想情况下,我想打印一个进度线。像

这样的东西
train 53/56...x6 │ loss:1.356 │ miou:0.276 │ rate=3.13 Hz, eta=0:00:01, total=0:00:17, wall=19:48 EST

然后,当下一行打印时,我想简单地覆盖这一行。

目前我可以通过在打印邮件之前打印回车'\r'来完成此操作。这会将光标返回到行的开头,然后覆盖该行。正是我想要的。

问题是当终端太小而整条线不适合时,线条会缠绕并且回车将我带到包裹线的开头,而不是线的绝对开头。

有没有办法可以将光标一直带回到正确行的开头?

1 个答案:

答案 0 :(得分:2)

您最常使用ANSI escape sequences for cursor movement

  
      
  • 定位光标:\033[<L>;<C>H\033[<L>;<C>f   将光标放在第L行和第C列。
  •   
  • 将光标向上移动N行:   \033[<N>A
  •   
  • 将光标向下移动N行:   \033[<N>B
  •   
  • 将光标向前移动N列:   \033[<N>C
  •   
  • 向后移动光标N列:   \033[<N>D
  •   
  • 保存光标位置:   \033[s
  •   
  • 恢复光标位置:   \033[u
  •   

光标位置保存/恢复似乎非常适用于您的情况,但遗憾的是,这两个代码并未受到许多终端仿真器的尊重。

它们在xtermxfce4-terminal中工作(除非在终端/滚动输出的最后一行,如注释中的@ThomasDickey所述)。尝试:

echo -e "\033[s" {1..100} "\033[u" "Overwrite"

对于其他终端模拟器,您可以试试\033[<N>A运气,将光标向上移动所需的行数,然后移至列0

如果您知道线的长度,可以使用(bash示例计算它(以及包裹时)的行数(请注意COLUMNS环境变量的用法):< / p>

line='...'
len=${#line}
rows=$((len / COLUMNS))

然后向上移动:

printf "\033[%dA" "$rows"

在Python中,您可以像以下一样使用它:

print("\033[s", "123"*100, "\033[u", "Overwrite", sep='')
print("\033[%dA" % 3, "Overwrite", sep='')

或者,用curses之类的东西来抽象所有这些。

Python解决方案

基于将光标向上移动N行 ANSI转义序列(应该适用于大多数终端仿真器),以及兼容Python的code for terminal width detection(在Python3中,您可以使用{ {1}}),这是一个概念验证演示,适用于滚动输出,适应行长度和更改终端宽度

shutil.get_terminal_size