带有块字符的终端中的文本进度条

新手上路,请多包涵

我写了一个简单的控制台应用程序来使用 ftplib 从 FTP 服务器上传和下载文件。

我希望该应用程序为用户显示其下载/上传进度的一些可视化;每次下载数据块时,我希望它提供进度更新,即使它只是一个数字表示,如百分比。

重要的是,我想避免擦除在前几行中打印到控制台的所有文本(即我不想在打印更新进度时“清除”整个终端)。

这似乎是一项相当常见的任务——我如何才能在保留先前程序输出的同时制作一个进度条或类似的可视化输出到我的控制台?

原文由 bobber205 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 532
2 个回答

蟒蛇3

一个简单的、可定制的进度条

以下是我经常使用的许多答案的汇总(不需要导入)。

注意: 此答案中的所有代码都是为 Python 3 创建的;请参阅答案结尾以将此代码与 Python 2 一起使用。

 # Print iterations progress
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█', printEnd = "\r"):
    """
    Call in a loop to create terminal progress bar
    @params:
        iteration   - Required  : current iteration (Int)
        total       - Required  : total iterations (Int)
        prefix      - Optional  : prefix string (Str)
        suffix      - Optional  : suffix string (Str)
        decimals    - Optional  : positive number of decimals in percent complete (Int)
        length      - Optional  : character length of bar (Int)
        fill        - Optional  : bar fill character (Str)
        printEnd    - Optional  : end character (e.g. "\r", "\r\n") (Str)
    """
    percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
    filledLength = int(length * iteration // total)
    bar = fill * filledLength + '-' * (length - filledLength)
    print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)
    # Print New Line on Complete
    if iteration == total:
        print()

示例用法

import time

# A List of Items
items = list(range(0, 57))
l = len(items)

# Initial call to print 0% progress
printProgressBar(0, l, prefix = 'Progress:', suffix = 'Complete', length = 50)
for i, item in enumerate(items):
    # Do stuff...
    time.sleep(0.1)
    # Update Progress Bar
    printProgressBar(i + 1, l, prefix = 'Progress:', suffix = 'Complete', length = 50)

示例输出

Progress: |█████████████████████████████████████████████-----| 90.0% Complete

更新

评论中讨论了一个允许进度条动态调整到终端窗口宽度的选项。虽然我不推荐这样做,但这里有一个实现此功能的 要点(并注明注意事项)。

以上的单一调用版本

下面的评论引用了针对类似问题发布的一个很好的 答案。我喜欢它展示的易用性并写了一个类似的,但选择 sys 模块的导入,同时添加原始的一些功能 printProgressBar 上面的函数.

与上面的原始函数相比,这种方法的一些好处包括消除了对函数的初始调用以在 0% 处打印进度条以及使用 enumerate 成为可选的(即不再明确要求使功能正常工作)。

 def progressBar(iterable, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█', printEnd = "\r"):
    """
    Call in a loop to create terminal progress bar
    @params:
        iterable    - Required  : iterable object (Iterable)
        prefix      - Optional  : prefix string (Str)
        suffix      - Optional  : suffix string (Str)
        decimals    - Optional  : positive number of decimals in percent complete (Int)
        length      - Optional  : character length of bar (Int)
        fill        - Optional  : bar fill character (Str)
        printEnd    - Optional  : end character (e.g. "\r", "\r\n") (Str)
    """
    total = len(iterable)
    # Progress Bar Printing Function
    def printProgressBar (iteration):
        percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
        filledLength = int(length * iteration // total)
        bar = fill * filledLength + '-' * (length - filledLength)
        print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)
    # Initial Call
    printProgressBar(0)
    # Update Progress Bar
    for i, item in enumerate(iterable):
        yield item
        printProgressBar(i + 1)
    # Print New Line on Complete
    print()

示例用法

import time

# A List of Items
items = list(range(0, 57))

# A Nicer, Single-Call Usage
for item in progressBar(items, prefix = 'Progress:', suffix = 'Complete', length = 50):
    # Do stuff...
    time.sleep(0.1)

示例输出

Progress: |█████████████████████████████████████████████-----| 90.0% Complete

蟒蛇2

要在 Python 2 中使用上述函数,请在脚本顶部将编码设置为 UTF-8:

 # -*- coding: utf-8 -*-

并替换此行中的 Python 3 字符串格式:

 print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)

使用 Python 2 字符串格式:

 print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end = printEnd)

原文由 Greenstick 发布,翻译遵循 CC BY-SA 4.0 许可协议

写入 ‘\r’ 会将光标移回行首。

这显示一个百分比计数器:

 import time
import sys

for i in range(100):
    time.sleep(1)
    sys.stdout.write("\r%d%%" % i)
    sys.stdout.flush()

原文由 Stephen 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题