Python类初始化加载pickle数据时如何添加实时进度条?
跨基类-派生类全初始化流程的实时进度条实现
核心实现逻辑
要实现覆盖「基类初始化启动到派生类初始化结束」的全流程进度条,核心是保证进度条实例的生命周期完全匹配整个加载区间,且顺着类的继承链透传同一个进度条对象,避免出现基类初始化完成就提前终止进度条的问题。
基础可运行实现
我们基于常用的tqdm进度条库实现,通过给构造函数新增可选的进度条入参,实现对原有代码无侵入的透传:
from tqdm import tqdm import pickle import os # 通用进度更新工具,无有效进度条时直接跳过,兼容原有无进度条的调用逻辑 def update_progress(pbar, advance): if pbar is not None: pbar.update(advance) class Base: # 新增可选pbar入参,接收外部传入的进度条实例 def __init__(self, pbar=None): # Loading starts here with open("base_cache.pkl", "rb") as f: self.some_data = pickle.load(f) # 基类数据加载完成后,推进对应占比的进度 update_progress(pbar, base_progress_step) class Derived(Base): def __init__(self, pbar=None): # 透传同一个进度条实例给父类构造函数,保证流程连贯 super().__init__(pbar=pbar) with open("derived_cache.pkl", "rb") as f: self.some_more_data = pickle.load(f) # Loading ends here # 派生类数据加载完成后,推进剩余进度 update_progress(pbar, derived_progress_step)
外层调用时,进度条的启动和关闭完全匹配加载流程的起止:
if __name__ == "__main__": # 按两个pickle文件的实际体积动态计算进度占比,避免硬编码占比不准的问题 base_size = os.path.getsize("base_cache.pkl") derived_size = os.path.getsize("derived_cache.pkl") total_size = base_size + derived_size # 换算成总长度100的整数步长 base_progress_step = round(100 * base_size / total_size) derived_progress_step = 100 - base_progress_step # 进入with块时启动进度条,此时还未执行任何类初始化逻辑 with tqdm(total=100, desc="全量数据加载") as main_pbar: # 将进度条传入派生类构造函数,顺着继承链完成全流程透传 obj = Derived(pbar=main_pbar) # 退出with块时,派生类的全部初始化逻辑已执行完毕,进度条自动关闭
优化方向
- 如果单个pickle文件体积过大,可以在分块读取文件的逻辑里拆分进度更新步骤,避免大文件读取时进度条长时间卡在某个数值不动
- 如果使用
rich等其他进度条库,实现逻辑完全一致:只需要把进度条实例顺着继承链透传,统一控制起止范围即可 - 由于构造函数的进度条参数是可选的,原有不传入进度条的旧调用方式(比如直接实例化
Derived())可以完全正常运行,不会出现逻辑报错
注意不要在基类或派生类的构造函数内部直接创建、关闭独立的进度条,这种方式会把基类和派生类的加载流程拆成两个独立的进度条,无法形成覆盖全流程的单一条目,也会出现进度条提前关闭的问题。
内容的提问来源于stack exchange,提问作者Filip Szczybura
相关产品推荐
相关产品推荐

