如何用Python案例实现进度条显示?

wen python案例 7

本文目录导读:

如何用Python案例实现进度条显示?

  1. 基础版本:使用 print 和 \r
  2. 进阶版本:完整的进度条类
  3. 使用 tqdm 库(推荐)
  4. 实际应用场景示例
  5. 自定义进度条的装饰器
  6. 选择建议

我来介绍几种在Python中实现进度条显示的方法,从简单到高级。

基础版本:使用 print 和 \r

import time
def simple_progress_bar(total=50):
    """简单的进度条实现"""
    for i in range(total+1):
        # 计算进度百分比
        percent = i / total * 100
        # 构建进度条显示
        bar_length = 30
        filled_length = int(bar_length * i / total)
        bar = '█' * filled_length + '░' * (bar_length - filled_length)
        # \r 回到行首,实现动态更新
        print(f'\r进度: |{bar}| {percent:.1f}% ({i}/{total})', end='', flush=True)
        time.sleep(0.1)
    print()  # 最后换行
# 运行示例
simple_progress_bar(50)

进阶版本:完整的进度条类

import time
import sys
class ProgressBar:
    """可重用的进度条类"""
    def __init__(self, total=100, bar_length=40, prefix='进度'):
        """
        初始化进度条
        Args:
            total: 总任务数
            bar_length: 进度条长度
            prefix: 前缀描述
        """
        self.total = total
        self.bar_length = bar_length
        self.prefix = prefix
        self.current = 0
    def update(self, step=1):
        """更新进度"""
        self.current += step
        if self.current > self.total:
            self.current = self.total
        self._display()
    def _display(self):
        """显示进度条"""
        percent = self.current / self.total * 100
        filled_length = int(self.bar_length * self.current / self.total)
        bar = '█' * filled_length + '░' * (self.bar_length - filled_length)
        sys.stdout.write(f'\r{self.prefix}: |{bar}| {percent:.1f}% ({self.current}/{self.total})')
        sys.stdout.flush()
        # 如果完成,换行
        if self.current >= self.total:
            print()
# 使用示例
def task_with_progress():
    progress = ProgressBar(total=30, bar_length=30, prefix='下载中')
    for i in range(30):
        time.sleep(0.15)  # 模拟耗时操作
        progress.update(1)
task_with_progress()

使用 tqdm 库(推荐)

# 需要先安装: pip install tqdm
from tqdm import tqdm
import time
# 基本用法
def basic_tqdm():
    # 在循环中使用
    for i in tqdm(range(100), desc="处理中"):
        time.sleep(0.05)
# 手动更新进度
def manual_tqdm():
    pbar = tqdm(total=50, desc="下载文件")
    for i in range(50):
        time.sleep(0.1)
        pbar.update(1)  # 每步增加1
    pbar.close()
# 嵌套进度条
def nested_tqdm():
    for i in tqdm(range(5), desc="外层任务"):
        for j in tqdm(range(20), desc=f"内层任务 {i}", leave=False):
            time.sleep(0.05)
# 自定义格式
def custom_tqdm():
    file_sizes = [1024, 2048, 512, 4096]  # 文件大小(KB)
    with tqdm(total=sum(file_sizes), unit='KB', 
              desc='下载进度', unit_scale=True) as pbar:
        for size in file_sizes:
            time.sleep(0.5)  # 模拟下载
            pbar.update(size)  # 更新实际大小
# 运行示例
print("=== 基本用法 ===")
basic_tqdm()
print("\n=== 手动更新 ===")
manual_tqdm()
print("\n=== tqdm 美化示例 ===")
# 使用 tqdm 的一些高级特性
from tqdm import trange
# 类似于 range 但带进度条
for i in trange(50, desc="处理中", ncols=70):
    time.sleep(0.1)

实际应用场景示例

import time
import random
from tqdm import tqdm
def simulate_file_download():
    """模拟文件下载"""
    total_size = 1024 * 10  # 10MB
    chunk_size = 64  # 每次64KB
    print("开始下载文件...")
    downloaded = 0
    with tqdm(total=total_size, unit='KB', 
              unit_scale=True, 
              desc="下载进度",
              bar_format='{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}]') as pbar:
        while downloaded < total_size:
            # 模拟下载一块数据
            time.sleep(0.1)
            chunk = random.randint(32, chunk_size)
            downloaded += chunk
            # 更新进度
            pbar.update(chunk)
    print("下载完成!")
def batch_process_with_progress():
    """批量处理文件"""
    files = [f"file_{i}.txt" for i in range(20)]
    results = []
    for file in tqdm(files, desc="批量处理", unit="files"):
        # 模拟处理文件
        time.sleep(0.2)
        # 模拟有时失败
        if random.random() < 0.1:
            tqdm.write(f"警告:处理 {file} 时出现问题")
        results.append(f"processed_{file}")
    return results
def download_with_eta():
    """带预计完成时间的下载"""
    import requests
    # 注意:这需要实际的网络请求,这里用模拟替代
    total = 100
    start_time = time.time()
    pbar = tqdm(total=total, desc="下载中", 
                bar_format='{l_bar}{bar}| {percentage:3.0f}% [{elapsed}<{remaining}]')
    for i in range(total):
        time.sleep(0.1)
        pbar.update(1)
        # 自定义后处理显示
        if i == 50:
            pbar.set_description("超过一半了")
        elif i == 80:
            pbar.set_description("即将完成")
    pbar.close()
    print(f"总耗时: {time.time() - start_time:.2f}秒")
# 运行示例
print("=== 文件下载模拟 ===")
simulate_file_download()
print("\n=== 批量处理 ====")
results = batch_process_with_progress()
print(f"处理完成 {len(results)} 个文件")
print("\n=== 带有ETA ===")
download_with_eta()

自定义进度条的装饰器

import time
from functools import wraps
from tqdm import tqdm
def progress_bar(total=None, desc="处理中"):
    """进度条装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 获取 total 值
            total_value = total
            if total_value is None and 'total' in kwargs:
                total_value = kwargs.pop('total')
            if total_value:
                with tqdm(total=total_value, desc=desc) as pbar:
                    kwargs['pbar'] = pbar
                    return func(*args, **kwargs)
            else:
                return func(*args, **kwargs)
        return wrapper
    return decorator
@progress_bar(desc="数据处理")
def process_data(total, pbar=None):
    result = []
    for i in range(total):
        time.sleep(0.1)
        result.append(i * 2)
        if pbar:
            pbar.update(1)
    return result
# 使用装饰器
result = process_data(30)
print(f"处理完成,结果长度: {len(result)}")

选择建议

  1. 简单场景:使用基础版本的 print + \r
  2. 需要更多功能:使用 tqdm 库(最推荐)
  3. 特定需求:自定义进度条类

tqdm 是 Python 社区最流行的进度条库,功能丰富、使用简单,建议在正式项目中使用。

抱歉,评论功能暂时关闭!