Pytube下载回调bytes_remaining统计不准、进度更新极慢问题排查
问题结论
该现象和短时间发起过多请求触发Pytube侧限流、过载没有任何关联,核心是Pytube默认下载逻辑与系统IO缓冲机制叠加导致的,即使无GUI的最简脚本也会稳定复现。
具体成因
- Pytube旧版本默认的下载分块(chunk)大小为9MB,
on_progress回调仅在单个完整分块从网络端接收完成后才会触发一次,并非按实时下载字节数持续触发。 - 操作系统默认开启文件写入缓冲:当网络下载速度较快时,Pytube会将接收的字节先存入系统写缓冲区,本地文件管理器会提前显示文件已达到完整体积,但此时Pytube仍在处理最后几个分块的接收、等待缓冲区数据刷入物理磁盘,回调返回的
bytes_remaining仍为按分块计数的旧值,就会出现“本地已生成完整文件,进度仍持续更新”的滞后现象,网络带宽越高滞后时长越明显,千兆网络环境下滞后可达1分钟以上。 - 之前功能正常属于偶发场景匹配:此前测试时要么下载的视频体积较小、分块总数少,要么当时网速较慢,分块下载间隔和磁盘刷写速度基本对齐,没有感知到明显偏差。
修复方案
- 方案1:修改Pytube源码配置
找到Python环境中Pytube安装目录下的request.py文件,定位到默认分块大小配置项,将原有的chunk_size = 9 * 1024 * 1024(9MB)修改为chunk_size = 256 * 1024(256KB),即可大幅提升回调触发频率,基本消除进度滞后问题。 - 方案2:不修改源码,手动实现下载逻辑指定分块大小
不直接调用默认的download()方法,自行实现文件写入逻辑,手动传入更小的分块参数,参考代码如下:
import pytube import os def on_progress(stream, chunk, bytes_remaining): total = stream.filesize downloaded = total - bytes_remaining print(f"当前进度: {round(downloaded / total * 100, 2)}%") def on_complete(stream, file_path): print("下载完成") video = pytube.YouTube("你的目标视频链接", on_progress_callback=on_progress, on_complete_callback=on_complete) stream = video.streams.get_highest_resolution() save_path = os.path.join("你的本地保存目录", stream.default_filename) with open(save_path, "wb") as f: # 指定256KB分块,替代默认9MB分块配置 for chunk in stream.iter_content(chunk_size=256*1024): f.write(chunk)
- Tkinter适配额外注意:如果是GUI场景,不要将下载任务放在Tkinter主线程运行,否则会阻塞UI事件循环,额外造成进度条刷新卡顿,需要将下载逻辑放到独立子线程中,通过线程队列或
after()方法将进度值传递到主线程更新UI。
内容的提问来源于stack exchange,提问作者Leo187_
相关产品推荐
相关产品推荐

