控制台中的文本进度栏

有没有一个好方法来做到以下几点?

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

每次下载一些数据块时,我想要更新文本进度条,即使它只是一个数字。

但我不想删除已经打印到控制台的所有文本。 (做一个“清除”,然后打印更新的百分比。)

以下是我经常使用的许多答案的汇总。

# Print iterations progress def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█'): """ 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) """ percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total))) filledLength = int(length * iteration // total) bar = fill * filledLength + '-' * (length - filledLength) print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end = '\r') # Print New Line on Complete if iteration == total: print() # # Sample Usage # from time import sleep # 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... sleep(0.1) # Update Progress Bar printProgressBar(i + 1, l, prefix = 'Progress:', suffix = 'Complete', length = 50) # Sample Output Progress: |█████████████████████████████████████████████-----| 90.0% Complete 

写入'\ r'会将光标移回到行首。

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

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

写一个\r到控制台。 这是一个“回车” ,导致行后的所有文本被回显。 就像是:

 def update_progress(progress): print '\r[{0}] {1}%'.format('#'*(progress/10), progress) 

这会给你类似的东西: [ ########## ] 100%

tqdm:在第二个循环中添加一个进度表 :

 >>> import time >>> from tqdm import tqdm >>> for i in tqdm(range(100)): ... time.sleep(1) ... |###-------| 35/100 35% [elapsed: 00:35 left: 01:05, 1.00 iters/sec] 

它不到10行代码。

这里的要点: https : //gist.github.com/vladignatyev/06860ec2040cb497f0f3

 import sys def progress(count, total, suffix=''): bar_len = 60 filled_len = int(round(bar_len * count / float(total))) percents = round(100.0 * count / float(total), 1) bar = '=' * filled_len + '-' * (bar_len - filled_len) sys.stdout.write('[%s] %s%s ...%s\r' % (bar, percents, '%', suffix)) sys.stdout.flush() # As suggested by Rom Ruben 

在这里输入图像描述

尝试使用Python的Mozart编写的点击库Armin Ronacher。

 $ pip install click # both 2 and 3 compatible 

创build一个简单的进度条:

 import click with click.progressbar(range(1000000)) as bar: for i in bar: pass 

这是它的样子:

 # [###-------------------------------] 9% 00:01:14 

定制你的心内容:

 import click, sys with click.progressbar(range(100000), file=sys.stderr, show_pos=True, width=70, bar_template='(_(_)=%(bar)sD(_(_| %(info)s', fill_char='=', empty_char=' ') as bar: for i in bar: pass 

自定义外观:

 (_(_)===================================D(_(_| 100000/100000 00:00:02 

还有更多选项,请参阅API文档 :

  click.progressbar(iterable=None, length=None, label=None, show_eta=True, show_percent=None, show_pos=False, item_show_func=None, fill_char='#', empty_char='-', bar_template='%(label)s [%(bar)s] %(info)s', info_sep=' ', width=36, file=None, color=None) 

我意识到我迟到了,但是这里有一个我写的轻微的Yum风格(红帽)(这里不是100%的准确性,但是如果你使用一个进度条来达到这个准确度,那么你无论如何都是错误的):

 import sys def cli_progress_test(end_val, bar_length=20): for i in xrange(0, end_val): percent = float(i) / end_val hashes = '#' * int(round(percent * bar_length)) spaces = ' ' * (bar_length - len(hashes)) sys.stdout.write("\rPercent: [{0}] {1}%".format(hashes + spaces, int(round(percent * 100)))) sys.stdout.flush() 

应该产生这样的东西:

 Percent: [############## ] 69% 

…支架保持静止,只有散列增加。

这可能会更好地作为装饰。 再过一天…

检查这个库: clint

它有很多function,包括进度条:

 from time import sleep from random import random from clint.textui import progress if __name__ == '__main__': for i in progress.bar(range(100)): sleep(random() * 0.2) for i in progress.dots(range(100)): sleep(random() * 0.2) 

此链接提供了其function的快速概述

下面是用Python编写的一个进度条的一个很好的例子: http : //nadiana.com/animated-terminal-progress-bar-in-python

但如果你想自己写。 你可以使用curses模块来让事情变得更简单:)

也许更容易不是诅咒的词。 但是如果你想创造一个完整的cui而不是诅咒为你处理很多东西。

由于旧的链接已经死了,我已经把自己的Python进度条的版本,这里得到它: https : //github.com/WoLpH/python-progressbar

 import time,sys for i in range(100+1): time.sleep(0.1) sys.stdout.write(('='*i)+(''*(100-i))+("\r [ %d"%i+"% ] ")) sys.stdout.flush() 

产量

[29%] ===================

并且,为了添加到堆中,可以使用这个对象

 import sys class ProgressBar(object): DEFAULT_BAR_LENGTH = 65 DEFAULT_CHAR_ON = '=' DEFAULT_CHAR_OFF = ' ' def __init__(self, end, start=0): self.end = end self.start = start self._barLength = self.__class__.DEFAULT_BAR_LENGTH self.setLevel(self.start) self._plotted = False def setLevel(self, level): self._level = level if level < self.start: self._level = self.start if level > self.end: self._level = self.end self._ratio = float(self._level - self.start) / float(self.end - self.start) self._levelChars = int(self._ratio * self._barLength) def plotProgress(self): sys.stdout.write("\r %3i%% [%s%s]" %( int(self._ratio * 100.0), self.__class__.DEFAULT_CHAR_ON * int(self._levelChars), self.__class__.DEFAULT_CHAR_OFF * int(self._barLength - self._levelChars), )) sys.stdout.flush() self._plotted = True def setAndPlot(self, level): oldChars = self._levelChars self.setLevel(level) if (not self._plotted) or (oldChars != self._levelChars): self.plotProgress() def __add__(self, other): assert type(other) in [float, int], "can only add a number" self.setAndPlot(self._level + other) return self def __sub__(self, other): return self.__add__(-other) def __iadd__(self, other): return self.__add__(other) def __isub__(self, other): return self.__add__(-other) def __del__(self): sys.stdout.write("\n") if __name__ == "__main__": import time count = 150 print "starting things:" pb = ProgressBar(count) #pb.plotProgress() for i in range(0, count): pb += 1 #pb.setAndPlot(i + 1) time.sleep(0.01) del pb print "done" 

结果是:

 starting things: 100% [=================================================================] done 

这通常被认为是“过顶”,但是当你使用它的时候很方便

在Python命令行中运行( 不在任何IDE或开发环境中):

 >>> import threading >>> for i in range(50+1): ... threading._sleep(0.5) ... print "\r%3d" % i, ('='*i)+('-'*(50-i)), 

在我的Windows系统上正常工作。

我正在使用reddit进度 。 我喜欢它,因为它可以打印一行中每个项目的进度,并且不应该从程序中清除打印输出。

编辑:固定链接

基于以上的答案和其他类似的关于CLI进度条的问题,我想我得到了一个普遍的答案。 检查它在https://stackoverflow.com/a/15860757/2254146

总之,代码是这样的:

 import time, sys # update_progress() : Displays or updates a console progress bar ## Accepts a float between 0 and 1. Any int will be converted to a float. ## A value under 0 represents a 'halt'. ## A value at 1 or bigger represents 100% def update_progress(progress): barLength = 10 # Modify this to change the length of the progress bar status = "" if isinstance(progress, int): progress = float(progress) if not isinstance(progress, float): progress = 0 status = "error: progress var must be float\r\n" if progress < 0: progress = 0 status = "Halt...\r\n" if progress >= 1: progress = 1 status = "Done...\r\n" block = int(round(barLength*progress)) text = "\rPercent: [{0}] {1}% {2}".format( "#"*block + "-"*(barLength-block), progress*100, status) sys.stdout.write(text) sys.stdout.flush() 

好像

百分比:[##########] 99.0%

我推荐使用tqdm – https://pypi.python.org/pypi/tqdm – 这使得将任何迭代或进程变成进度条变得简单,并且处理所有需要的terminal的混乱。

从文档:“tqdm可以很容易地支持callback/钩子和手动更新。这里是一个例子urllib”

 import urllib from tqdm import tqdm def my_hook(t): """ Wraps tqdm instance. Don't forget to close() or __exit__() the tqdm instance once you're done with it (easiest using `with` syntax). Example ------- >>> with tqdm(...) as t: ... reporthook = my_hook(t) ... urllib.urlretrieve(..., reporthook=reporthook) """ last_b = [0] def inner(b=1, bsize=1, tsize=None): """ b : int, optional Number of blocks just transferred [default: 1]. bsize : int, optional Size of each block (in tqdm units) [default: 1]. tsize : int, optional Total size (in tqdm units). If [default: None] remains unchanged. """ if tsize is not None: t.total = tsize t.update((b - last_b[0]) * bsize) last_b[0] = b return inner eg_link = 'http://www.doc.ic.ac.uk/~cod11/matryoshka.zip' with tqdm(unit='B', unit_scale=True, miniters=1, desc=eg_link.split('/')[-1]) as t: # all optional kwargs urllib.urlretrieve(eg_link, filename='/dev/null', reporthook=my_hook(t), data=None) 
 import sys def progresssbar(): for i in range(100): time.sleep(1) sys.stdout.write("%i\r" % i) progressbar() 

注意:如果您在交互式联机程序中运行此function,则会打印出额外的数字

大声笑我只是写了一个这个inheritance人的代码记住你不能使用unicode当做块ascii我使用cp437

 import os import time def load(left_side, right_side, length, time): x = 0 y = "" print "\r" while x < length: space = length - len(y) space = " " * space z = left + y + space + right print "\r", z, y += "█" time.sleep(time) x += 1 cls() 

你就这样称呼它

 print "loading something awesome" load("|", "|", 10, .01) 

所以看起来像这样

 loading something awesome |█████ | 

有了上面的伟大build议,我可以找出进度条。

不过,我想指出一些缺点

  1. 每当进度条被刷新时,它就会从新的一行开始

     print('\r[{0}]{1}%'.format('#' * progress* 10, progress)) 

    喜欢这个:
    [] 0%
    [#] 10%
    [##] 20%
    [###] 30%

2.方括号']'和右边的百分数右移,'###'变长。
3.如果expression式“progress / 10”不能返回一个整数,则会发生错误。

下面的代码将解决上面的问题。

 def update_progress(progress, total): print('\r[{0:10}]{1:>2}%'.format('#' * int(progress * 10 /total), progress), end='') 

pythonterminal进度条代码

 import sys import time max_length = 5 at_length = max_length empty = "-" used = "%" bar = empty * max_length for i in range(0, max_length): at_length -= 1 #setting empty and full spots bar = used * i bar = bar+empty * at_length #\r is carriage return(sets cursor position in terminal to start of line) #\0 character escape sys.stdout.write("[{}]\0\r".format(bar)) sys.stdout.flush() #do your stuff here instead of time.sleep time.sleep(1) sys.stdout.write("\n") sys.stdout.flush() 

把我在这里find的一些想法放在一起,并增加估计的时间:

 import datetime, sys start = datetime.datetime.now() def print_progress_bar (iteration, total): process_duration_samples = [] average_samples = 5 end = datetime.datetime.now() process_duration = end - start if len(process_duration_samples) == 0: process_duration_samples = [process_duration] * average_samples process_duration_samples = process_duration_samples[1:average_samples-1] + [process_duration] average_process_duration = sum(process_duration_samples, datetime.timedelta()) / len(process_duration_samples) remaining_steps = total - iteration remaining_time_estimation = remaining_steps * average_process_duration bars_string = int(float(iteration) / float(total) * 20.) sys.stdout.write( "\r[%-20s] %d%% (%s/%s) Estimated time left: %s" % ( '='*bars_string, float(iteration) / float(total) * 100, iteration, total, remaining_time_estimation ) ) sys.stdout.flush() if iteration + 1 == total: print # Sample usage for i in range(0,300): print_progress_bar(i, 300) 

那么这里的代码是有效的,我在发布之前对它进行了testing:

 import sys def prg(prog, fillchar, emptchar): fillt = 0 emptt = 20 if prog < 100 and prog > 0: prog2 = prog/5 fillt = fillt + prog2 emptt = emptt - prog2 sys.stdout.write("\r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%") sys.stdout.flush() elif prog >= 100: prog = 100 prog2 = prog/5 fillt = fillt + prog2 emptt = emptt - prog2 sys.stdout.write("\r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%" + "\nDone!") sys.stdout.flush() elif prog < 0: prog = 0 prog2 = prog/5 fillt = fillt + prog2 emptt = emptt - prog2 sys.stdout.write("\r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%" + "\nHalted!") sys.stdout.flush() 

优点:

  • 20个字符(每5个字符1个字符)
  • 自定义填充字符
  • 自定义空白字符
  • 停止(低于0的任何数字)
  • 完成(100和100以上的任何数字)
  • 进度计数(0-100(特殊function以下和以上))
  • 栏旁边的百分比数字,是一行

缺点:

  • 仅支持整数(可以修改为支持它们,通过使除法为整数除法,所以只需将prog2 = prog/5更改为prog2 = int(prog/5)

这是我的Python 3解决scheme:

 import time for i in range(100): time.sleep(1) s = "{}% Complete".format(i) print(s,end=len(s) * '\b') 

'\ b'是一个反斜杠,用于string中的每个字符。 这在Windows cmd窗口中不起作用。

从Greenstick 2.7的function:

 def printProgressBar (iteration, total, prefix = '', suffix = '',decimals = 1, length = 100, fill = '#'): percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total))) filledLength = int(length * iteration // total) bar = fill * filledLength + '-' * (length - filledLength) print'\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), sys.stdout.flush() # Print New Line on Complete if iteration == total: print() 

python模块进度条是一个不错的select。 这是我的典型代码:

 import time import progressbar widgets = [ ' ', progressbar.Percentage(), ' ', progressbar.SimpleProgress(format='(%(value_s)s of %(max_value_s)s)'), ' ', progressbar.Bar('>', fill='.'), ' ', progressbar.ETA(format_finished='- %(seconds)s -', format='ETA: %(seconds)s', ), ' - ', progressbar.DynamicMessage('loss'), ' - ', progressbar.DynamicMessage('error'), ' ' ] bar = progressbar.ProgressBar(redirect_stdout=True, widgets=widgets) bar.start(100) for i in range(100): time.sleep(0.1) bar.update(i + 1, loss=i / 100., error=i) bar.finish() 

https://pypi.python.org/pypi/progressbar2/3.30.2

Progressbar2是用于命令行导入时间导入进度条的ascii基础进度条的一个很好的库

 bar = progressbar.ProgressBar() for i in bar(range(100)): time.sleep(0.02) bar.finish() 

https://pypi.python.org/pypi/tqdm

tqdm是progressbar2的替代品,我认为它在pip3中使用,但我不确定

 from tqdm import tqdm for i in tqdm(range(10000)): ... 

我写了一个简单的进度条:

 def bar(total, current, length=10, prefix="", filler="#", space=" ", oncomp="", border="[]", suffix=""): if len(border) != 2: print("parameter 'border' must include exactly 2 symbols!") return None print(prefix + border[0] + (filler * int(current / total * length) + (space * (length - int(current / total * length)))) + border[1], suffix, "\r", end="") if total == current: if oncomp: print(prefix + border[0] + space * int(((length - len(oncomp)) / 2)) + oncomp + space * int(((length - len(oncomp)) / 2)) + border[1], suffix) if not oncomp: print(prefix + border[0] + (filler * int(current / total * length) + (space * (length - int(current / total * length)))) + border[1], suffix) 

正如你所看到的,它具有:条的长度,前缀和后缀,填充符,空格,100%(oncomp)和边框上的文本

这里是一个例子:

 from time import sleep, time start_time = time() for i in range(10): pref = str((i+1) * 10) + "% " complete_text = "done in %s sec" % str(round(time() - start_time)) sleep(1) bar(10, i + 1, length=20, prefix=pref, oncomp=complete_text) 

正在进行中:

 30% [###### ] 

完整的:

 100% [ done in 9 sec ]