我编写了一个简单的控制台应用程序,使用ftplib从FTP服务器上传和下载文件。
我想应用程序显示一些可视化的下载/上传进度为用户;每次下载数据块时,我希望它提供一个进度更新,即使它只是一个数字表示,如百分比。
重要的是,我想避免擦除之前打印到控制台的所有文本(即,我不想在打印更新的进度时“清除”整个终端)。
这似乎是一个相当常见的任务——我如何才能制作一个进度条或类似的可视化输出到我的控制台,同时保留之前的程序输出?
我编写了一个简单的控制台应用程序,使用ftplib从FTP服务器上传和下载文件。
我想应用程序显示一些可视化的下载/上传进度为用户;每次下载数据块时,我希望它提供一个进度更新,即使它只是一个数字表示,如百分比。
重要的是,我想避免擦除之前打印到控制台的所有文本(即,我不想在打印更新的进度时“清除”整个终端)。
这似乎是一个相当常见的任务——我如何才能制作一个进度条或类似的可视化输出到我的控制台,同时保留之前的程序输出?
当前回答
尝试安装这个包:pip install progressbar2:
import time
import progressbar
for i in progressbar.progressbar(range(100)):
time.sleep(0.02)
进度栏 GitHub: https://github.com/WoLpH/python-progressbar
其他回答
根据上面的答案和其他类似的关于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%
检查这个库:clint
它有很多功能,包括一个进度条:
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)
此链接提供了其功能的快速概述
试试由Python界的莫扎特Armin Ronacher编写的点击库。
$ pip install click # both 2 and 3 compatible
创建一个简单的进度条:
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)
根据上面的建议,我制作了进度条。
然而,我想指出一些缺点
每次刷新进度条时,它将从新一行开始 打印(‘\ r({0}){1} %’。格式('#' * progress* 10, progress)) 是这样的: [] 0% [#] 10% (# #) 20% (# # #) 30%
2.方括号“]”和右边的百分数随着“###”变长而右移。 3.如果表达式'progress / 10'不能返回整数,则会发生错误。
下面的代码将修复上面的问题。
def update_progress(progress, total):
print('\r[{0:10}]{1:>2}%'.format('#' * int(progress * 10 /total), progress), end='')
我推荐使用tqdm - https://pypi.python.org/pypi/tqdm -它可以简单地将任何可迭代对象或进程转换为进度条,并处理所需终端的所有混乱。
从文档中可以看到:“tqdm可以很容易地支持回调/钩子和手动更新。这里有一个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)