我编写了一个简单的控制台应用程序来使用 ftplib 从 FTP 服务器上传和下载文件。
我希望该应用程序为用户显示其下载/上传进度的一些可视化;每次下载数据块时,我希望它提供进度更新,即使它只是像百分比这样的数字表示。
重要的是,我想避免擦除在前几行中打印到控制台的所有文本(即,我不想在打印更新的进度时“清除”整个终端)。
这似乎是一个相当常见的任务——我如何才能制作一个进度条或类似的可视化输出到我的控制台,同时保留以前的程序输出?
以下是我经常使用的许多答案的汇总(不需要导入)。
注意:此答案中的所有代码都是为 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函数的一些特性。
sys
printProgressBar
与上述原始函数相比,这种方法的一些好处包括消除了对函数的初始调用以在 0% 处打印进度条以及使用enumerate变得可选(即不再明确要求使函数工作)。
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)
要在 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)