Python递归检测txt含password时返回空列表问题修复
问题产生原因
- 递归逻辑设计错误:每次进入
search_pass_file函数都会新建一个空的list_of_pass结果列表,之前递归层中匹配到的文件路径不会被累计保存。只要遇到第一个触发异常的文件,代码就直接返回下一层递归的结果,当前层已经查到的匹配路径会被直接丢弃。 - 遍历逻辑存在bug:你用
for i in range(len(list_of_files))固定初始长度做循环,但循环内部不断调用pop()修改原列表长度,会导致遍历提前终止、漏处理文件,甚至索引报错。 - 编码设置不合理:强制用
utf-8编码打开所有txt文件,Windows环境下大量txt文件使用GBK、GB2312等本地编码,极易触发UnicodeDecodeError,进一步放大递归丢结果的问题。 - 前置扫描逻辑有隐患:
search_txt中调用os.walk时没有做异常处理,碰到系统保护、无权限访问的目录会直接抛出异常终止扫描,根本拿不到完整的txt文件列表。
原递归写法修复
要修复递归版本需要调整4个核心点:
- 将结果列表作为可选参数传入递归函数,避免每次递归重置结果
- 触发异常时不要直接返回递归结果,仅跳过当前异常文件,再递归处理剩余文件
- 移除循环内修改原列表的
pop()逻辑,避免遍历长度错乱 - 给
os.walk增加错误忽略配置,碰到无权限目录自动跳过
修复后的代码如下:
import os def search_txt(): """遍历C盘收集所有.txt后缀文件的完整路径""" list_of_txt = [] # 加onerror参数忽略无权限目录的错误 for dir_path, sub_dir, files in os.walk("C:\\", onerror=lambda e: None): for file in files: if file.endswith(".txt"): list_of_txt.append(os.path.join(dir_path, file)) return list_of_txt def search_pass_file(list_of_files: list, list_of_pass=None): """遍历文本文件查找包含"password"关键词的文件路径""" # 初始化结果列表,仅在第一次调用时创建空列表 if list_of_pass is None: list_of_pass = [] if not list_of_files: return list_of_pass # 取第一个文件处理,剩余文件留到递归层 current_file = list_of_files[0] remaining_files = list_of_files[1:] try: # 增加errors="ignore"避免编码问题中断 with open(current_file, encoding="utf8", errors="ignore") as f: for line in f: if "password" in line: list_of_pass.append(current_file) break # 命中后不用继续读当前文件 except (UnicodeDecodeError, PermissionError): pass # 异常直接跳过当前文件即可 # 递归处理剩余文件,传入已累计的结果列表 return search_pass_file(remaining_files, list_of_pass) if __name__ == '__main__': myList = search_txt() print(search_pass_file(myList))
更优的非递归实现
这个场景完全不需要用递归,普通循环实现逻辑更直白,也不会出现递归深度超限的问题(C盘文件数量极多时递归层数过大会触发栈溢出),性能和可维护性都更好:
import os def search_txt(): """遍历C盘收集所有.txt后缀文件的完整路径""" list_of_txt = [] for dir_path, sub_dir, files in os.walk("C:\\", onerror=lambda e: None): for file in files: if file.lower().endswith(".txt"): # 兼容.TXT大写后缀的情况 list_of_txt.append(os.path.join(dir_path, file)) return list_of_txt def search_pass_file(list_of_files: list): """遍历文本文件查找包含"password"关键词的文件路径""" list_of_pass = [] for file_path in list_of_files: try: # 逐行读取,不用一次性读全文件占内存,加errors忽略解码异常 with open(file_path, encoding="utf-8", errors="ignore") as f: for line in f: if "password" in line.lower(): # 兼容大写的PASSWORD关键词 list_of_pass.append(file_path) break except (PermissionError, OSError): # 捕获更多IO相关异常,比如文件被占用 continue return list_of_pass if __name__ == '__main__': myList = search_txt() print(search_pass_file(myList))
额外优化点:如果需要更精准的编码识别,可以不用硬编码utf-8,改用编码检测类库识别文件编码后再打开,不过日常扫描场景用
errors="ignore"已经足够覆盖需求。
内容的提问来源于stack exchange,提问作者Professor Seemo
相关产品推荐
相关产品推荐

