在日常开发中,出现了一些业务要求查看进度的需求,这里我想到了进度条,自己看了一些资料,自己做了一些整理。这边和大家分享一下。
1 背景知识
1.1 sys.stdout 与 print
当我们在 Python 中打印对象调用 print(obj) 时候,事实上是调用了 sys.stdout.write(obj+'\n')
print 将你需要的内容打印到了控制台,然后追加了一个换行符,即print 会调用 sys.stdout 的 write 方法
以下两行在事实上等价:
sys.stdout.write('hello'+'\n')
print('hello')
1.2 sys.stdout.flush()
在Linux系统下,必须加入sys.stdout.flush()才能一秒输一个数字
在Windows系统下,加不加sys.stdout.flush()都能一秒输出一个数字
import sys
import time
for i in range(100):
time.sleep(0.1)
sys.stdout.write("\r" + str(i))
sys.stdout.flush()
1.3 set_description()
set_description() 为进度条设置描述
import time
from tqdm import tqdm
# 增加描述, 设置进度内容
pbar = tqdm(["a", "b", "c", "d"])
for char in pbar:
time.sleep(0.1)
pbar.set_description("Processing %s" % char)
运行效果:
2 代码实现
import sys
import time
from tqdm import tqdm
# 基本范例
for i in tqdm(range(100)):
time.sleep(0.01)
# 增加描述, 设置进度内容
pbar = tqdm(["a", "b", "c", "d"])
for char in pbar:
time.sleep(0.1)
pbar.set_description("Processing %s" % char)
# 手动更新
# 一共100个,每次更新10,一共更新10次
with tqdm(total=100) as pbar:
# 一共更新10次
for i in range(10):
time.sleep(0.1)
# 每次更新10
pbar.update(10)
# Appendix: 手工实现循环进度条
def progress_bar(num, total):
rate = float(num) / total
ratenum = int(100 * rate)
r = "\r{}{}{}%".format("█" * ratenum, " " * (100 - ratenum), ratenum)
sys.stdout.write(r)
sys.stdout.flush()
n = 100
for i in range(n):
time.sleep(0.05)
progress_bar(i + 1, n)
3 python的tkinter进度条的实现
import time
import tkinter as tk
# 创建主窗口
window = tk.Tk()
window.title('进度条')
window.geometry('630x150')
# 设置下载进度条
tk.Label(window, text='下载进度:', ).place(x=10, y=60)
canvas = tk.Canvas(window, width=465, height=22, bg="white")
canvas.place(x=110, y=60)
# 显示下载进度
def progress():
# 填充进度条
fill_line = canvas.create_rectangle(1.5, 1.5, 0, 23, width=0, fill="green")
x = 500 # 未知变量,可更改
n = 465 / x # 465是矩形填充满的次数
for i in range(x):
n = n + 465 / x
canvas.coords(fill_line, (0, 0, n, 60))
window.update()
time.sleep(0.02) # 控制进度条流动的速度
# 清空进度条
fill_line = canvas.create_rectangle(1.5, 1.5, 0, 23, width=0, fill="white")
x = 500 # 未知变量,可更改
n = 465 / x # 465是矩形填充满的次数
for t in range(x):
n = n + 465 / x
# 以矩形的长度作为变量值更新
canvas.coords(fill_line, (0, 0, n, 60))
window.update()
time.sleep(0) # 时间为0,即飞速清空进度条
btn_download = tk.Button(window, text='启动进度条', command=progress)
btn_download.place(x=400, y=105)
window.mainloop()
运行效果: