当前位置:首页 > 文章列表 > 文章 > python教程 > Python Path.iterdir 遇到权限错误时怎么继续扫描

Python Path.iterdir 遇到权限错误时怎么继续扫描

来源:17golang原创 2026-09-07 23:36:49 0浏览 收藏

用 Path.iterdir() 扫描目录时,最稳妥的处理不是在整棵目录树外面包一个大 try,而是把异常边界放在“当前目录”这一层:当前目录没有读取权限就记录下来,继续处理其他目录;拿到子路径后,再分别判断它是目录还是普通文件。

关键点是把“无法读取目录”和“路径不是目录”分开。iterdir() 访问不可用目录时会抛出 OSError(常见表现是 PermissionError),而 is_dir()、is_file() 可能把不可访问路径返回为 False。所以结果里要保留 skipped_paths,不能把它们悄悄算成普通文件。

先记住三个结果: files 是确认过的文件,visited_dirs 是进入过的目录,skipped_paths 是本轮没有权限或检查失败的路径。

先把扫描范围和相对路径固定下来

问题现场通常从一个相对目录开始,例如用户传入 data/incoming。如果程序中途切换工作目录,后续拼接出来的路径就可能指向另一个位置。入口处只做一次解析:先用 Path 表达路径,再用 resolve() 得到明确根目录。子路径用斜杠运算符拼接,不要把字符串和分隔符混在一起。

from pathlib import Path

def scan_tree(root_text: str):
    # 只在入口确定一次根目录,避免相对路径随工作目录变化
    root = Path(root_text).expanduser().resolve()
    return root

root = scan_tree("data/incoming")
child = root / "2026" / "09"
print(root)
print(child)

这里的 resolve() 解决的是“从哪里扫”的问题,不代表目录一定可读。路径解析成功后,仍然要在真正调用 iterdir() 的位置处理权限。

Path.resolve、相对路径、Path.iterdir 和 PermissionError 的静态边界关系图
图1:把路径解析、相对路径拼接和目录读取异常放在不同边界内,扫描范围才不会失控。

在每个 Path.iterdir() 边界捕获权限异常

Path.iterdir() 返回的是迭代器,异常可能在开始取值时出现。因此要在遍历当前目录的局部位置捕获 OSError,而不是只捕获创建迭代器的那一行。权限不足时,把当前目录写入 skipped_paths,然后返回空列表,外层队列仍可继续。

def safe_children(directory: Path, skipped_paths: list[Path]):
    # 目录不可访问只影响当前节点,不终止整棵树
    try:
        return list(directory.iterdir())
    except OSError as exc:
        skipped_paths.append(directory)
        print(f"跳过 {directory}: {exc}")  # 保留可追踪的原因
        return []

捕获范围建议使用 OSError,因为文件系统错误不只有 PermissionError,还可能有目录消失、挂载点短暂不可用等情况。如果业务必须区分权限拒绝,再对 PermissionError 单独计数。

用 Path.is_dir() 和 Path.is_file() 分开判断类型

拿到 child 后不要靠后缀判断目录。目录继续进入待扫描队列,普通文件才加入 files。类型判断也要有异常边界:在网络盘或目录被并发删除时,判断结果可能已经失效;这类路径应进入跳过清单,避免报告看起来“扫描完成”但实际漏掉对象。

def scan_tree(root: Path):
    pending = [root]
    files, visited_dirs, skipped_paths = [], [], []

    while pending:
        # 从队列取一个目录;列表只保存 Path,不保存不稳定的字符串
        directory = pending.pop()
        visited_dirs.append(directory)
        for child in safe_children(directory, skipped_paths):
            try:
                if child.is_dir():
                    pending.append(child)
                elif child.is_file():
                    files.append(child)
            except OSError as exc:
                skipped_paths.append(child)
                print(f"无法判断 {child}: {exc}")

    return files, visited_dirs, skipped_paths

这段代码的边界很清楚:iterdir() 负责拿到当前目录的孩子,is_dir() 和 is_file() 负责分类。不要把 False 直接改写成“文件”,因为不可访问和非文件是两件事。

Path.iterdir 子路径经过目录判断和文件判断后进入结果清单的静态关系图
图2:同一个 child path 经过目录判断和文件判断后,分别归入继续扫描、文件结果或跳过记录。

用结果清单确认哪些路径被跳过

调用方最终至少要拿到三类结果,而不是只返回一个文件列表。这样可以把“没有文件”和“没有权限看到文件”区分开。

结果含义建议动作
files已确认是普通文件继续读取或交给后续处理
visited_dirs程序尝试进入的目录用于统计扫描范围
skipped_paths权限、消失或类型判断失败告警、重试或交给管理员处理

如果 skipped_paths 非空,报告应明确写出“部分路径未扫描”,而不要输出“扫描完成”这种容易误解的结论。需要完整读取时,再从权限、挂载状态或运行账号入手修复环境;代码本身只负责可控地跳过并留下证据。

Path.glob() 能不能直接替代?

如果只需要匹配文件名,glob() 或 rglob() 更省代码;但它们会抑制扫描阶段的部分 OSError,不适合要求列出每个跳过目录的审计型任务。

为什么不用 os.walk()?

os.walk() 也能配合错误回调继续遍历。本文保留 Path 链路,是为了让路径拼接、类型判断和结果记录保持同一种对象模型;如果项目已经围绕文件描述符或大量目录做性能优化,再考虑切换实现。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go coverprofile 看不到子包覆盖率时怎么指定包范围Go coverprofile 看不到子包覆盖率时怎么指定包范围
上一篇
Go coverprofile 看不到子包覆盖率时怎么指定包范围
Go 模板执行后输出空字符串怎么区分零值和缺失字段
下一篇
Go 模板执行后输出空字符串怎么区分零值和缺失字段
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • SuperCLUE中文大模型评测基准:功能、能力维度与应用指南
    SuperCLUE
    SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
    173次使用
  • C-Eval中文评测基准:大语言模型多学科能力评估指南
    C-Eval
    深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
    106次使用
  • AI Prompt Library:免费AI提示词库,助力ChatGPT高效创作与营销
    AI Prompt Library
    探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
    34次使用
  • LangGPT提示词框架:结构化Prompt设计方法与开源工具指南
    LangGPT
    LangGPT是一种受编程语言启发的结构化提示词设计工具,提供双层框架、模块化模板及变量功能,帮助用户高效编写高质量Prompt。该项目已在GitHub免费开源,适用于内容创作、编程辅助等多场景。
    42次使用
  • ClickPrompt:AI提示词生成与优化工具,支持Stable Diffusion、ChatGPT及代码辅助
    ClickPrompt
    ClickPrompt是一款专为AI提示词编写者设计的开源在线工具,支持Stable Diffusion绘图、ChatGPT对话及GitHub Copilot代码辅助。提供Prompt自动生成、一键运行、社区分享及可视化优化功能,帮助用户高效获取精准AI输出。
    79次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码