Azure Data Lake Gen2目录大小计算递归深度超限问题解决求助
解决Azure Data Lake Gen2目录大小计算的递归深度与内存问题
你的问题核心在于递归方式不适合处理层级极深或文件数量极大的目录——Python的递归栈天生有深度限制,就算手动调高sys.setrecursionlimit,遇到超深层目录还是会触发RecursionError;同时递归过程中不断拼接新列表的操作,也会导致内存占用飙升,最终引发OOM。
下面是用**迭代(栈模拟)**改写的解决方案,彻底解决这两个问题:
import sys from dbutils import FileInfo root_path = "/mnt/datalake/.../" def discover_size(path: str, verbose: bool = True): total_size = 0.0 # 用列表模拟栈,初始压入根目录的文件/子目录 stack = dbutils.fs.ls(path) while stack: # 弹出栈顶元素处理(pop()是深度优先,和原递归逻辑一致;用pop(0)可切换为广度优先) item = stack.pop() if item.size > 0: # 是文件,累加大小 file_size_mb = item.size / 1e6 total_size += file_size_mb if verbose: print(f"Processed file {item.path}, size: {file_size_mb:.2f} MB") else: # 是目录,把目录下的所有元素压入栈,继续处理 stack.extend(dbutils.fs.ls(item.path)) return total_size # 调用函数 total = discover_size(root_path, verbose=True) print(f"Total directory size: {total:.2f} MB")
为什么这个方案能解决问题?
- 摆脱递归深度限制:用循环+栈的迭代方式,完全脱离了Python递归栈的深度约束,不管目录层级多深都能稳定处理。
- 优化内存占用:不再像递归那样每次创建新的列表切片和拼接结果,而是直接在栈上添加/移除元素,内存占用始终保持在可控范围内,不会因文件数量过多爆发式增长。
- 灵活的遍历顺序:默认用
pop()实现深度优先遍历(和你原递归逻辑一致),若需广度优先,只需替换为pop(0)即可。
额外优化建议
如果verbose=True时打印太多文件导致性能下降,可以改成按批次打印进度,降低IO开销:
count = 0 while stack: item = stack.pop() if item.size > 0: total_size += item.size / 1e6 count +=1 if verbose and count % 1000 == 0: print(f"Processed {count} files, current total: {total_size:.2f} MB")
内容的提问来源于stack exchange,提问作者Master_GoGo
相关产品推荐
相关产品推荐

