3

我在这里想知道的东西应该是真正的“基本”,但这是我长期以来的一个问题,不知道诀窍在哪里。

假设在一个耗时的程序中(bash或者Python),我必须在运行时打印出进度的百分比,基本上我想打印1%,并且在一定时间后,我打印2%等等。我想'2%'成为完全显示在显示的相同位置'1%',而不是像“1% 2%”之类的。你知道wget,我想要的正是 wget 所做的,显示下载进度的进度。我是否需要清除以前打印的字符,但是如何?

基本是怎么操作的...

谢谢,

4

4 回答 4

6

我将用 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')

输出:

短线很长的线

一个典型的解决方案是在长行上写空格。

于 2012-06-22T04:02:34.300 回答
1

提供了一个 Python 解决方案,在 bash 中并不是特别困难(或不同):

i=20
while (( i-- ))
do
    echo -ne "\r$i% done  "
    sleep 1
done

echo

bash中flush不需要,因为echo无论如何都会调用它。的参数echo-n抑制换行,并-e翻译\r符号。请注意字符串中文本末尾带有几个空格的hack,以清除到行尾。

于 2012-06-22T07:50:23.813 回答
1

这是一个简单的计时器,也许可以帮助您;-) 写另一个字符以使用打印功能覆盖当前位置。

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")
于 2014-06-06T16:23:00.007 回答
1

在 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='')
于 2018-05-23T02:14:15.587 回答