暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

用python实现一个进度条,包含原理讲解

coolpython 2021-04-28
1155

python的进度条有很多第三方库,有些做的比较炫酷,一直都比较好奇进度条的原理,今天研究了一番,如果想要实现一个简单的进度条,还是很容易的。


1. 进度条原理




进度条的难点在于,进度的输出内容始终都在同一行,而平时使用print输出时,都会默认换行,这样就不能实现进度条推进增长的效果了。只要能实现所有输出内容在同一行,后面的输出覆盖前面的输出,进度条也就实现了。而要实现这一点,却是如此的简单,print函数的原型如下

def print(self, *args, sep=' ', end='\n', file=None):


end默认值是'\n', 表示回车,会换到下一行,把end设置成'\r' ,就不会换到下一行,而是将光标移动到当前行的首位,后面输出的内容,自然就覆盖了前面的内容

import time


for i in range(100):
print(i, end='\r')
time.sleep(0.1)

代码运行起来后,不换行原地从0输出到99。运行这段代码,一定要在终端里,如果是windows系统,请在cmd里运行,或者在pycharm的Terminal里运行,否则是看不到效果的。

掌握了原理,自己就可以实现一个简单的进度条工具了

2. 设计一个简单的进度条




class EasyProcessBar():
def __init__(self, name, total):
self.name = name # 进度条明后才能
self.total = total # 进度总数
self.complete_count = 0 # 已经完成的进度数
self.char_count = 0 # 需要显示的进度字符个数
self.char_show_count = 0 # 已经显示的进度字符个数


sz = os.get_terminal_size() # 获取终端长和宽
self.char_count = sz.columns - len(name) - 15

设计一个EasyProcessBar类

  • name显示在进度条的最前方

  • 既然是显示进度,自然需要知道总进度大小和已经完成的进度数量

  • 进度条用#来显示,#的数量不需要和total相同,因为屏幕的宽度是有限的,但total是可以随意设置的

  • os.get_terminal_size()可以获得终端的宽度,宽度减去name的长度,在预留15个字符的宽度用于显示进度百分比,剩余的就是需要显示的#的数量

  • 在不同大小的终端里,进度条的大小也不一样,显示会更美观

3. 更新进度




    def update(self, incr=1):
self.complete_count += incr
if self.complete_count >= self.total:
self.complete_count = self.total


self.flush()

提供一个update方法,用于更新进度,complete_count大于total是不合理的,最大只能等于total, 更新进度后,要刷新输出


4. 刷新输出




    def flush(self):
sys.stdout.write(self.process_string)
sys.stdout.flush()

我使用了sys.stdout.write方法来输出进度条


5. 生成进度显示内容




    @property
def process_string(self):
"""
进度
:return:
"""
ratio = self.complete_count/self.total # 已经完成的百分比
char_show_count = int(ratio * self.char_count) # 需要显示的#的数量
if char_show_count > self.char_show_count:
self.char_show_count = char_show_count


# 进度条,预留出足够的宽度给百分比
process = "{process:<{count}}".format(process="#"*self.char_show_count, count=self.char_count)
percent = '{:.0%}'.format(ratio) # 百分比
line = f"{self.name} {process} {percent}\r"
return line


process_string 是进度条的核心,要计算出当前时刻的百分比,初始化process字符串,它就是动态增长的进度条


6. 全部代码和测试




import os
import sys
import time
import random




class EasyProcessBar():
def __init__(self, name, total):
self.name = name # 进度条明后才能
self.total = total # 进度总数
self.complete_count = 0 # 已经完成的进度数
self.char_count = 0 # 需要显示的进度字符个数
self.char_show_count = 0 # 已经显示的进度字符个数


sz = os.get_terminal_size() # 获取终端长和宽
self.char_count = sz.columns - len(name) - 15


@property
def process_string(self):
"""
进度
:return:
"""
ratio = self.complete_count/self.total # 已经完成的百分比
char_show_count = int(ratio * self.char_count) # 需要显示的#的数量
if char_show_count > self.char_show_count:
self.char_show_count = char_show_count


# 进度条,预留出足够的宽度给百分比
process = "{process:<{count}}".format(process="#"*self.char_show_count, count=self.char_count)
percent = '{:.0%}'.format(ratio) # 百分比
line = f"{self.name} {process} {percent}\r"
return line


def update(self, incr=1):
self.complete_count += incr
if self.complete_count >= self.total:
self.complete_count = self.total


self.flush()


def flush(self):
sys.stdout.write(self.process_string)
sys.stdout.flush()








epb = EasyProcessBar("download", 130)
for i in range(130):
epb.update()
time.sleep(random.uniform(0.1, 0.5))

实际运行时的效果

download ##############                                   15%



文章转载自coolpython,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论