在我的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'
来完成此操作。这会将光标返回到行的开头,然后覆盖该行。正是我想要的。
问题是当终端太小而整条线不适合时,线条会缠绕并且回车将我带到包裹线的开头,而不是线的绝对开头。
有没有办法可以将光标一直带回到正确行的开头?
答案 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
光标位置保存/恢复似乎非常适用于您的情况,但遗憾的是,这两个代码并未受到许多终端仿真器的尊重。
它们在xterm
和xfce4-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
之类的东西来抽象所有这些。
基于将光标向上移动N行 ANSI转义序列(应该适用于大多数终端仿真器),以及兼容Python的code for terminal width detection(在Python3中,您可以使用{ {1}}),这是一个概念验证演示,适用于滚动输出,适应行长度和更改终端宽度:
shutil.get_terminal_size