Pytube下载YouTube视频时os.stat获取文件大小不连续更新如何解决
问题原因与解决方案
根因说明
这个现象不是os模块导致的,是Pytube的默认缓存写入机制+操作系统文件页缓存共同造成的:
- Pytube默认采用大缓冲块下载,不会每下载一点就写入磁盘。你本次下载的13MB左右的480p视频,默认会分2次写入磁盘:第一次写入约9.5MB(对应71%进度),第二次写入剩余的3.8MB(直接到100%),写入前文件系统记录的大小不会更新,所以你读不到中间值。
- 操作系统会对文件写入做页缓存,就算应用发起写入请求,数据也会先暂存在内核缓存中,不会立刻更新磁盘文件的大小元数据,只有缓存刷入磁盘后你才能通过os.stat读到更新后的大小。
os.stat和os.path.getsize的行为完全正常,二者底层都是调用操作系统的stat接口获取文件元信息,返回结果一致属于预期现象,不存在os模块的bug。
解决方案
方案1(最推荐):使用Pytube内置进度回调
不需要额外运行独立检测脚本,直接在下载进程内获取实时进度,完全绕过文件系统缓存问题,示例代码:
from pytube import YouTube # 进度回调函数 def on_progress(stream, chunk, bytes_remaining): total = stream.filesize downloaded = total - bytes_remaining percent = (downloaded / total) * 100 print(f"{percent:.1f}% 已下载") url = "https://www.youtube.com/watch?v=ERMRVORGvZM" r = "480p" # 初始化时绑定进度回调 yt = YouTube(url, on_progress_callback=on_progress) yt.streams.filter(res=r).first().download("your_save_path")
方案2:必须使用独立检测脚本的调整方法
如果业务要求必须用独立进程检测进度,做两处修改:
- 调整Pytube下载逻辑,缩小写入块并强制刷盘,修改下载代码如下:
from pytube import YouTube import os url = "https://www.youtube.com/watch?v=ERMRVORGvZM" r = "480p" yt = YouTube(url) stream = yt.streams.filter(res=r).first() # 自定义流式下载,每次写128KB就刷盘 with open(os.path.join("your_save_path", f"{stream.default_filename}"), "wb") as f: for chunk in stream.iter_chunk(chunk_size=131072): # 128KB 块大小 if chunk: f.write(chunk) f.flush() os.fsync(f.fileno()) # 强制刷入磁盘,跳过系统缓存
- 调整检测脚本,增加延时、异常捕获和正确的字符串拼接:
import os import time title = "Run Python script on clicking HTML button Script Output on Html Page Part1" total_size = 13370966 save_path = "your_save_path" file_path = os.path.join(save_path, f"{title}.mp4") while True: try: current_size = os.path.getsize(file_path) except FileNotFoundError: # 下载刚启动文件还未创建,等待 time.sleep(0.2) continue percent = (current_size / total_size) * 100 print(f"{percent:.1f}% Downloaded") if percent >= 100: break time.sleep(0.2) # 每次循环暂停0.2秒,避免空占CPU
内容的提问来源于stack exchange,提问作者farhan ahmed FCS
相关产品推荐
相关产品推荐

