有时候一个任务特别耗时,用户需要知道到底这个程序运行到了什么状态,或者用户需要知道这个程序死掉了还是在运行,这时使用 进度条是非常有必要的。
如何实现进度条呢?
原理是输出字符串时,不输出换行符,下次输出直接跳到行首继续输出。这里面跳到行首是最重要的,一般是 \r 来完成。
也就是说,当一个字符串里面包含 \r 时,\r 后面的字符其实是跳到行首输出的。这样会把 \r 前面的字符 盖掉。
下载 exmaples/e03.py
# -*- coding: utf-8 -*-from __future__ import absolute_import,
unicode_literalsimport sysimport timeCNT = 5for i in range(CNT): sys.stdout.write('现在进行到:%d/%d\r' % (i+1, CNT))
# 往标准输出缓冲区打印字符 sys.stdout.flush() # 把缓冲区里面的字符打印到标准输出 time.sleep(1) # 模拟耗时操作
有些聪明的读者可能发现,当新的字符串比之前短的时候会出现问题。其实是因为已经被flush出去的字符并不会主动清空,所以 只有新写入的被修改了。针对这点我目前的解决方案是先输出一波空格把之前的字符串冲掉然后重新写:
# -*- coding: utf-8 -*-from __future__ import absolute_import,
unicode_literalsimport sysimport timeCNT = 5for i in range(CNT): sys.stdout.write(' '*100 + '\r') # 在输出之前先清空缓冲区 sys.stdout.flush() sys.stdout.write('现在进行到:%d/%d\r' % (i+1, CNT))
# 往标准输出缓冲区打印字符 sys.stdout.flush() # 把缓冲区里面的字符打印到标准输出 time.sleep(1) # 模拟耗时操作
现在又有个问题,我还想print,但是进度条随着print的内容移动,一直保证其在最下方,看例子:
下载 exmaples/e05.py
# -*- coding: utf-8 -*-from __future__ import absolute_import,
unicode_literalsimport sysimport timeCNT = 5for i in range(CNT): sys.stdout.write(' '*100 + '\r') # 在输出之前先清空缓冲区 sys.stdout.flush() print('现在下载到第%d个' % (i+1)) sys.stdout.write('现在进行到:%d/%d\r' % (i+1, CNT))
# 往标准输出缓冲区打印字符 sys.stdout.flush() # 把缓冲区里面的字符打印到标准输出 time.sleep(1) # 模拟耗时操作
为什么进度栏会一直在最下面,因为print打印出了换行符,下次打印进度栏的时候自然到最下面去了。
一个真正的进度条:
下载 exmaples/e06.py
# -*- coding: utf-8 -*-from __future__ import absolute_import,
unicode_literalsimport sysimport timeCNT = 100for i in range(CNT): sys.stdout.write(' '*100 + '\r') sys.stdout.flush() sys.stdout.write('%d/%d [' % (i+1, CNT) + '#'*i + ' ]\r') sys.stdout.flush() time.sleep(1)
看到这,有人又要问了,这个还是有点麻烦,有没有简便的方法,其实还真有。
拿Python来说有个简单的库: progressbar2,可以实现。
安装progressbar2:
pip install progressbar2
例如:
下载 exmaples/e07.py
from __future__ import absolute_import, unicode_literalsimport
timefrom progressbar import ProgressBarCNT = 100with
ProgressBar(max_value=CNT) as bar: for i in range(CNT): bar.update(i+1) time.sleep(1)
欢迎点击阅读原文前往下载源代码
欢迎关注生信人