tqdm 是最轻量且兼容性最好的文件读取进度条方案,应直接包裹文件迭代器而非一次性加载;对无法获取大小的流式数据需禁用百分比,改用绝对计数模式。

用 tqdm 包裹文件读取迭代器最直接
Python 标准库不自带进度条,tqdm 是最轻量、兼容性最好、且能自动适配文件读取节奏的方案。它不依赖文件大小预估,而是基于实际读取的行数或字节数更新进度。
常见错误是试图对整个文件一次性 read() 后再传给 tqdm,这会失去流式读取优势,还可能爆内存。正确做法是把文件对象本身(或其迭代器)交给 tqdm:
- 按行读:直接
tqdm(open("data.txt")),但要注意文件编码和关闭问题;更稳妥写法是用with open(...) as f: for line in tqdm(f): ... - 按块读(二进制/大文件):用
for chunk in tqdm(iter(lambda: f.read(8192), b"")):,其中8192是每次读取字节数 -
tqdm默认显示迭代次数,若想显示已读字节数,需手动传入total=os.path.getsize(filename)并在循环中累加计数
读取时不知道文件大小?别硬算 os.path.getsize
很多场景下,你读的可能是管道、网络响应流或临时生成的文件句柄,根本无法或不该调用 os.path.getsize。强行调用会失败(如 OSError: [Errno 29] Illegal seek),或导致重复打开、权限问题。
这时必须放弃“百分比”类进度,改用“已处理 X 行 / X 块”的绝对计数模式:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 用
tqdm(..., unit="line", unit_scale=False)显示行数,避免尝试计算百分比 - 若用
readlines(),tqdm会一次性加载全部内容到内存,这不是真流式读取——务必避开 - 从
requests.Response.iter_lines()或subprocess.Popen.stdout读取时,同样只能用无total的tqdm
rich.progress 更适合复杂进度场景,但引入成本略高
如果你需要多任务并行进度、自定义栏样式、或实时刷新的文件大小估算(比如边下载边解压),rich.progress 比 tqdm 更灵活。但它要求显式管理 Progress 实例和 Task,代码稍长。
关键差异点:
-
tqdm是函数式封装,一行就能加;rich需先创建Progress对象,再add_task,最后update -
rich支持TransferSpeedColumn和FileSizeColumn,但前提是你要自己维护已读字节数变量 - 如果项目已用
rich做日志或 CLI 输出,复用它的进度组件更统一;否则单为进度条引入rich略重
别忽略编码和换行符对行计数的影响
用 tqdm(f) 按行读时,进度条显示的“行数”严格等于 for line in f 触发的迭代次数。但不同平台换行符(\r\n vs \n)、BOM 头、或文件末尾是否换行,都会影响实际行数。这本身不是 bug,但容易让人误判“为什么进度卡在 99%”。
- Windows 上用
open(..., newline='')可标准化换行处理,但不会改变tqdm计数逻辑 - 若文件含空行或超长行,
tqdm的刷新频率可能滞后——这是终端渲染限制,不是代码问题 - 真正要校验进度准确性,得靠业务逻辑:比如每行解析后做计数器 +1,而不是只信
tqdm的计数
进度条的本质是反馈,不是精确仪表。文件读取快慢受磁盘、缓存、编码解析共同影响,强行绑定“百分比”反而容易误导。真正该关注的是:是否在流式读、是否没吃光内存、是否能及时中断。其他都是锦上添花。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










