如何解决Python目录递归遍历中的‘Too many open files’错误?
问题分析与修复方案
原代码的核心问题
- 无限递归调用:函数里每次递归都传入
rootdir,相当于反复扫描同一个根目录,无限调用自身,疯狂创建文件句柄,直接耗尽系统的文件描述符配额,触发Too many open files错误,最终导致栈溢出出现段错误。 - 逻辑顺序错误:
sys.exit("Directory is empty")之后的if dir.is_dir()永远不会执行,而且空目录的判断放在循环遍历每个条目的时候,完全不符合逻辑——应该是进入目录后先检查是否为空,而不是遍历每个条目都检查一次。 - 冗余操作:循环内重复调用
os.listdir(rootdir),完全没必要,浪费系统资源。
修复后的递归实现
先修正递归逻辑,确保只遍历每个子目录一次:
import os import sys rootdir = 'build/system/' def list_dirs(current_dir): # 先尝试获取目录条目 try: entries = os.scandir(current_dir) except OSError as e: print(f"无法访问目录 {current_dir}: {e}") return has_entries = False for entry in entries: has_entries = True if entry.is_dir(follow_symlinks=False): # 可选:跳过符号链接避免循环 # 在这里执行你需要的操作,比如打印目录路径 print(f"处理目录: {entry.path}") # 递归遍历子目录,传入当前子目录的路径 list_dirs(entry.path) # 显式关闭迭代器(Python 3.6+会自动处理,显式操作更稳妥) entries.close() if not has_entries: print(f"空目录: {current_dir}") # 若遇到空目录需要终止程序,取消下面注释 # sys.exit("Directory is empty") # 启动遍历 list_dirs(rootdir)
更优的非递归实现(推荐)
如果子目录层级极深,递归可能触发RecursionError(栈溢出),推荐用Python内置的os.walk,它是迭代式实现,更高效且避免递归栈问题:
import os import sys rootdir = 'build/system/' for dirpath, dirnames, filenames in os.walk(rootdir): # dirpath是当前目录路径,dirnames是当前目录下的子目录列表 print(f"处理目录: {dirpath}") # 如果需要处理空目录 if not dirnames and not filenames: print(f"空目录: {dirpath}") # 若遇到空目录要终止程序,取消下面注释 # sys.exit("Directory is empty")
为什么能解决问题
- 修复后的递归代码:每次递归传入当前子目录的路径,不会重复扫描根目录,避免了无限递归,同时合理处理了空目录判断和资源释放。
os.walk:Python内部用迭代方式遍历目录树,不需要手动管理递归栈,也不会因为层级过深导致栈溢出,而且底层实现高效,能避免文件句柄泄漏问题。
内容的提问来源于stack exchange,提问作者LM10
相关产品推荐
相关产品推荐

