s3fs 连续 glob 少了文件:前缀子集污染了目录缓存
先查 train-* 后 test-* 变空,可能是旧后端把前缀结果当成完整目录。核同实例与真实对象,清指定缓存并采用匹配的 s3fs/fsspec 正式组合。
同一个 S3 文件系统对象,先查 train-* 能找到文件,再查同目录的 test-* 却返回空列表;对应对象明明还在,exists() 也可能变成 False。如果换成新的受控文件系统实例、清掉该目录缓存后结果恢复,要检查前缀过滤的结果是否被误当成完整目录。
fsspec 2026.4.0 引入 glob 前缀提示后出现过这条 S3 路径:远端只返回符合前缀的对象,旧后端把这个子集写进整个父目录的缓存。下次查另一个前缀时,看到的就只有上一次的部分列表。
先证实两个结果来自同一份缓存
保留实际 fsspec、s3fs 版本和调用顺序,确认使用的是同一个实例、同一存储入口与凭据。对象名只是示例,权限、版本化对象及远端确实被删除等情况仍应独立排除。
对已确认的缓存路径,可在原实例上让指定目录重新获取列表:
directory = "example-bucket/data"
fs.invalidate_cache(directory)
test_files = fs.glob(directory + "/test-*")
这里的 fs 是已有、正确配置的 s3fs 同步实例,目录应换成受影响的 bucket/key 前缀,不包含凭据。这一操作清理客户端目录缓存,不删除远端对象;它也不是永远有效的修正,旧路径可能在后续 glob 中再次写入部分列表。
不要仅因一次缓存失效后找到文件,就把之前的所有“缺文件”结果都当成同一原因。记录第二次 glob、直接对象元数据查询及实际读取的结果,避免把权限拒绝、错误 endpoint 或另一套凭据误判成缓存污染。
更新的是后端缓存行为,不只看 fsspec 版本
当前正式 s3fs 2026.9.0 已在相关路径中区分前缀子集:带 prefix 的 _find 不把结果写成完整目录缓存,目录列表层也保留部分结果标记。应选择与它匹配的 fsspec 组合,并让应用实际加载新环境。
s3fs 2026.9.0 声明的 fsspec 范围是 >=2026.9.0,<2026.9.1。不要单独强装一个不满足后端约束的 fsspec,也不能把其他异步文件系统直接认定为同样已修正;缓存归属和处理要按实际后端核对。
已经污染的长生命周期实例不会因磁盘依赖文件更新就自行重建。通过应用正常生命周期更换实例,或在受控切换中处理已有目录缓存;不要在并发任务中随意替换共享对象。
按不同前缀的先后顺序验收
在授权的测试 bucket 中,保留同目录下两种前缀的固定对象,分别检查先 train 后 test、先 test 后 train,以及重复查同一前缀。每次都核对完整预期集合,不能只看列表非空。
再检查 info()、exists() 和真实读取是否一致,覆盖分页与目录深度等实际使用条件。列出一部分对象成功,不证明下一次前缀查找没有被旧缓存限制。
若下游已经把空列表当成“没有待处理数据”,更换依赖不会自动补回漏掉的任务。保留原对象清单与执行记录,按业务幂等规则复核缺项,不直接重跑整桶数据或重新上传原本存在的对象。


