用Python替换控制台输出

dut*_*utt 85 python

我想知道如何在Python中创建一个漂亮的控制台计数器,就像在某些C/C++程序中一样.

我有一个循环做事,当前的输出是这样的:

Doing thing 0
Doing thing 1
Doing thing 2
...
Run Code Online (Sandbox Code Playgroud)

什么是最简单的就是让最后一行更新;

X things done.
Run Code Online (Sandbox Code Playgroud)

我在许多控制台程序中看到过这种情况,我想知道是否/如何在Python中执行此操作.

650*_*502 124

一个简单的解决方案就是"\r"在字符串之前写入而不添加换行符; 如果字符串永远不会变短,这就足够了......

sys.stdout.write("\rDoing thing %i" % i)
sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)

进度条稍微复杂一点......这是我正在使用的东西:

def startProgress(title):
    global progress_x
    sys.stdout.write(title + ": [" + "-"*40 + "]" + chr(8)*41)
    sys.stdout.flush()
    progress_x = 0

def progress(x):
    global progress_x
    x = int(x * 40 // 100)
    sys.stdout.write("#" * (x - progress_x))
    sys.stdout.flush()
    progress_x = x

def endProgress():
    sys.stdout.write("#" * (40 - progress_x) + "]\n")
    sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)

您调用startProgress传递操作的描述,然后progress(x)在哪里x是百分比,最后endProgress()

  • @ math2001用空格填充. (5认同)
  • 如果字符串比前一个短怎么办? (2认同)

Ara*_*ggu 33

更优雅的解决方案可能是:

def progressBar(value, endvalue, bar_length=20):

        percent = float(value) / endvalue
        arrow = '-' * int(round(percent * bar_length)-1) + '>'
        spaces = ' ' * (bar_length - len(arrow))

        sys.stdout.write("\rPercent: [{0}] {1}%".format(arrow + spaces, int(round(percent * 100))))
        sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)

用value和endvalue调用这个函数,结果应该是

Percent: [------------->      ] 69%
Run Code Online (Sandbox Code Playgroud)


Joo*_*oop 30

python 3中,您可以这样做以在同一行上打印:

print('', end='\r')

跟踪最新的更新和进度特别有用。

如果想查看循环的进度,我还会从这里推荐 tqdm。它将当前迭代和总迭代打印为带有预期完成时间的进度条。超级有用和快速。适用于 python2 和 python3。


Iva*_*ich 15

我不久前写了这篇文章,对此感到非常满意。随意使用它。

它需要一个indexandtotal和可选的titleor bar_length。完成后,用复选标记替换沙漏。

? Calculating: [?????????????????????????] 18.0% done

? Calculating: [?????????????????????????] 100.0% done

我提供了一个可以运行来测试它的示例。

import sys
import time

def print_percent_done(index, total, bar_len=50, title='Please wait'):
    '''
    index is expected to be 0 based index. 
    0 <= index < total
    '''
    percent_done = (index+1)/total*100
    percent_done = round(percent_done, 1)

    done = round(percent_done/(100/bar_len))
    togo = bar_len-done

    done_str = '?'*int(done)
    togo_str = '?'*int(togo)

    print(f'\t?{title}: [{done_str}{togo_str}] {percent_done}% done', end='\r')

    if round(percent_done) == 100:
        print('\t?')


r = 50
for i in range(r):
    print_percent_done(i,r)
    time.sleep(.02)
Run Code Online (Sandbox Code Playgroud)

我还有一个带有响应式进度条的版本,具体取决于终端宽度shutil.get_terminal_size()(如果感兴趣)。


Sum*_*abh 8

如果我们查看print()函数,可以不使用 sys 库来完成

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

def update(n):
    for i in range(n):
        print("i:",i,sep='',end="\r",flush=True)
        #time.sleep(1)
Run Code Online (Sandbox Code Playgroud)


Bry*_*law 7

另一个答案可能更好,但这就是我在做的事情.首先,我创建了一个名为progress的函数,用于打印退格字符:

def progress(x):
    out = '%s things done' % x  # The output
    bs = '\b' * 1000            # The backspace
    print bs,
    print out,
Run Code Online (Sandbox Code Playgroud)

然后我在主函数的循环中调用它,如下所示:

def main():
    for x in range(20):
        progress(x)
    return
Run Code Online (Sandbox Code Playgroud)

这当然会抹掉整条线,但是你可以把它搞得一团糟去做你想要的.我最终使用这种方法制作了一个进度条.

  • 可以工作,但如果前一行的字符多于下一行,则新行结束后的字符将保留在上一行:"拼写检查记录417/701 [serfice更改为表面]当] uminescence] cence] shmentarianism] " (4认同)

jat*_*255 7

对于那些多年后偶然发现的人(就像我一样),我稍微调整了6502的方法,以允许进度条减少和增加.在更多的情况下有用.感谢6502一个伟大的工具!

基本上,唯一的区别是每次调用progress(x)时都会写入#s和-s的整行,并且光标总是返回到条的开头.

def startprogress(title):
    """Creates a progress bar 40 chars long on the console
    and moves cursor back to beginning with BS character"""
    global progress_x
    sys.stdout.write(title + ": [" + "-" * 40 + "]" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = 0


def progress(x):
    """Sets progress bar to a certain percentage x.
    Progress is given as whole percentage, i.e. 50% done
    is given by x = 50"""
    global progress_x
    x = int(x * 40 // 100)                      
    sys.stdout.write("#" * x + "-" * (40 - x) + "]" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = x


def endprogress():
    """End of progress bar;
    Write full bar, then move to next line"""
    sys.stdout.write("#" * 40 + "]\n")
    sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)


sor*_*rin 6

如果我理解得很好(不确定)你想要使用<CR>而不是<LR>

如果是这样,这是可能的,只要控制台终端允许这样(当输出si重定向到文件时它会中断).

from __future__ import print_function
print("count x\r", file=sys.stdout, end=" ")
Run Code Online (Sandbox Code Playgroud)


Nil*_*ils 5

为Aravind Voggu的示例添加了更多功能:

def progressBar(name, value, endvalue, bar_length = 50, width = 20):
        percent = float(value) / endvalue
        arrow = '-' * int(round(percent*bar_length) - 1) + '>'
        spaces = ' ' * (bar_length - len(arrow))
        sys.stdout.write("\r{0: <{1}} : [{2}]{3}%".format(\
                         name, width, arrow + spaces, int(round(percent*100))))
        sys.stdout.flush()
        if value == endvalue:     
             sys.stdout.write('\n\n')
Run Code Online (Sandbox Code Playgroud)

现在您可以生成多个进度条,而无需替换前一个进度条。

我还添加了name一个具有固定宽度的值。

对于两次循环和两次使用,progressBar()结果将如下所示:

进度条动画