我在这里想知道的东西应该是真正的“基本”,但这是我长期以来的一个问题,不知道诀窍在哪里。
假设在一个耗时的程序中(bash
或者Python
),我必须在运行时打印出进度的百分比,基本上我想打印1%
,并且在一定时间后,我打印2%
等等。我想'2%'
成为完全显示在显示的相同位置'1%'
,而不是像“1% 2%”之类的。你知道wget
,我想要的正是 wget 所做的,显示下载进度的进度。我是否需要清除以前打印的字符,但是如何?
基本是怎么操作的...
谢谢,
我将用 Python 回答,因为它更容易。
您可以在终端打印退格键将光标向左移动,然后写入另一个字符以覆盖当前位置。您也可以使用回车符转到行首。
import time
import sys
for x in range(101):
sys.stdout.write('\r%d%%' % x)
sys.stdout.flush()
time.sleep(0.2)
sys.stdout.write('\n')
使用回车并重写整行是最简单的,因为您不必注意要打印多少退格。
请注意,如果新行比旧行短,旧行仍会显示出来。
import sys
sys.stdout.write('this is a very long line')
sys.stdout.write('\rshort line')
sys.stdout.write('\n')
输出:
短线很长的线
一个典型的解决方案是在长行上写空格。
提供了一个 Python 解决方案,在 bash 中并不是特别困难(或不同):
i=20
while (( i-- ))
do
echo -ne "\r$i% done "
sleep 1
done
echo
bash中flush
不需要,因为echo
无论如何都会调用它。的参数echo
,-n
抑制换行,并-e
翻译\r
符号。请注意字符串中文本末尾带有几个空格的hack,以清除到行尾。
这是一个简单的计时器,也许可以帮助您;-) 写另一个字符以使用打印功能覆盖当前位置。
from __future__ import print_function
def timer():
for h in range(0, 24):
for m in range(0, 60):
for s in range(0, 60):
time.sleep(1)
print ("Elapsed time : %s:%s:%s" % (h, m, s), end="\r")
在 Python 3.6+ 中,Deitrich 的答案可以缩短为
import time
for i in range(101):
print(f'\r{i}%', end='')
time.sleep(0.01)
回车将您带回到行首,并传入一个空字符串作为 end 参数阻止您移动到下一行。
当我不知道一个动作需要多长时间时,我还发现这个生成器很有用。它将打印出三个点加载动画。在 Python 3.3+ 中工作
def loading_dots():
while True:
yield("\r. ")
yield("\r.. ")
yield("\r...")
你会像这样使用它
max_attempts = 100
dots = loading_dots()
for i in range(max_attempts):
if is_finished(): # you would have to create this function
break
time.sleep(2)
print(next(dots), end="", flush=True)
else:
raise Exception("timed out")
如果你想清除当前行,你可以这样做(Python 3.3+)
print('\r' + ' '*80 + '\r', end='')