登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  python教程

Python pathlib.Path.mkdir 的 parent_mode 怎么影响中间目录

来源:17golang原创

时间:2026-09-09 06:45:22 243浏览 收藏

如果你在 Python 3.15 中用 pathlib.Path.mkdir(parents=True) 创建 cache/service/v1,又希望叶目录和中间目录采用不同权限,答案是:把叶目录权限交给 mode,把递归创建的中间目录权限交给新增的 parent_mode。两者都会再经过进程的 umask,而且 parent_mode 只有在 parents=True 时才有意义。

要点速览
  • mode 控制本次目标叶目录,parent_mode 控制缺失的中间目录。
  • 已存在的父目录不会被 mkdir 重新改权限,exist_ok=True 也不会改变它。
  • Python 3.14 及更早版本不认识 parent_mode,需要先创建,再用 os.chmod 调整。

Python 3.15 的变化到底改了什么

过去,Path.mkdir(mode=..., parents=True) 可以递归补齐缺失目录,但 mode 主要对应最终目标目录;中间目录按系统默认创建权限处理。Python 3.15 给签名增加了关键字参数 parent_mode,让调用者明确表达“中间目录要用什么模式”。

这里的“中间目录”是目标路径最后一段之前缺失的那些目录。例如目标是 cache/service/v1,如果三个目录都不存在,v1 是叶目录,cacheservice 是中间目录。parents=True 负责允许递归创建,parent_mode 只负责补齐中间层。

Python pathlib Path.mkdir 中 mode、parent_mode、umask 与叶目录和中间目录的静态关系图
图1:Path.mkdir 的参数边界:mode 负责叶目录,parent_mode 负责递归创建的中间目录,最终模式还会受 umask 影响。

mode、parent_mode 和 umask 怎么分工

可以先记住下面这张边界表。它比“把两个参数都设成同一个八进制值”更能避免误解:

对象参数或因素作用
目标叶目录mode设置最终目录的请求模式
缺失中间目录parent_mode设置递归补齐的父级目录模式
所有新建目录umask参与计算最终实际权限
已存在目录exist_ok影响报错策略,不负责改权限

最小写法如下。0o750 只给叶目录使用,0o710 给中间目录使用;这段代码不需要手动拆分路径。

from pathlib import Path

target = Path("cache/service/v1")
# 叶目录使用 mode,中间目录使用 parent_mode。
target.mkdir(
    mode=0o750,
    parents=True,
    exist_ok=True,
    parent_mode=0o710,
)

注意两个边界:第一,父目录已经存在时,parent_mode 不会追溯修改它;第二,权限位还会受到 umask 影响,所以代码中的模式是请求值,不一定等于 stat().st_mode 读到的最终值。

为旧版本保留兼容写法

如果项目还支持 Python 3.14 或更早版本,不能无条件传入 parent_mode,否则旧解释器会因为不接受这个关键字而失败。兼容思路是先递归创建,再只调整这次确实缺失的父级目录;不要顺手修改整个已有目录树。

import os
from pathlib import Path

def mkdir_with_parent_mode(path: Path, leaf_mode: int, parent_mode: int) -> None:
    # 记录创建前不存在的祖先,避免改动原本已有的目录权限。
    missing = []
    current = path.parent
    while not current.exists():
        missing.append(current)
        current = current.parent

    # 旧版本只使用 parents 和叶目录的 mode。
    path.mkdir(mode=leaf_mode, parents=True, exist_ok=True)
    for directory in missing:
        # 从外层到内层调整,保证每个新建父目录都被覆盖。
        os.chmod(directory, parent_mode)

这个封装的取舍很明确:Python 3.15 可以直接使用新参数;旧版本则多一步权限调整。若目录创建发生并发竞争,权限修改仍应放在受控部署流程中,并结合进程的 umask 与平台权限模型测试。

Python 3.15 与旧版本 Path.mkdir 和 os.chmod 的目录权限兼容关系图
图2:版本兼容关系:Python 3.15 可在一次 mkdir 调用中表达两种模式,旧版本需要先建目录再显式调整父目录。

最小验证清单:别只看调用没有报错

验证时使用一个全新的临时根目录,分别检查叶目录和每一级中间目录的模式。不要只测目标目录,因为那只能证明 mode 起作用,无法证明 parent_mode 真的覆盖了递归层。

  1. 确认运行解释器版本;只有 Python 3.15 才直接测试 parent_mode
  2. 让目标路径的父级全部不存在,再调用 mkdir(parents=True)
  3. stat().st_mode & 0o777 读取各级目录,并把当前 umask 纳入预期。
  4. 再次调用并确认 exist_ok=True 不会把已有父目录改成新的 parent_mode

如果部署环境必须支持多个 Python 小版本,更稳妥的做法是把兼容封装集中在一个文件里,并在 CI 矩阵中覆盖“全新目录”和“部分目录已存在”两种状态。这样升级到 3.15 时,只需替换实现,不必让业务代码到处判断版本。

常见问题

parent_mode 能修改已经存在的父目录吗?

不能。它只参与新建的中间目录;已有目录的权限需要显式调用权限 API,并应评估是否会影响其他进程。

把 mode 和 parent_mode 设成一样是不是就没有区别?

结果可能相同,但职责仍不同:前者描述叶目录,后者描述递归创建的中间目录。保留分开设置的写法,后续调整权限策略时更清楚。

旧版本能不能用位置参数传 parent_mode?

不能。新参数是关键字参数,而且旧版本连这个参数名都不支持;应采用先创建再调整父目录的兼容封装。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>