Python os.makedirs 函数
上次修改时间:2025 年 4 月 11 日
这份全面的指南探讨了 Python 的 os.makedirs
函数,该函数递归地创建目录。我们将涵盖基本用法、exist_ok 参数、权限处理以及实际的目录创建示例。
基本定义
os.makedirs
函数递归地创建目录,包括所有必需的父目录。它类似于 Unix 中的 mkdir -p。
关键参数:name(要创建的路径)、mode(权限,默认为 0o777)、exist_ok(如果存在则阻止错误,默认为 False)。失败时引发 OSError。
基本目录创建
os.makedirs
最简单的用法是创建单个目录或嵌套目录结构。此示例演示了这两种情况。
import os # Create a single directory os.makedirs("my_directory") print("Created my_directory") # Create nested directories os.makedirs("parent/child/grandchild") print("Created parent/child/grandchild structure") # Verify creation print(os.listdir("parent/child"))
这会创建一个单个目录和一个嵌套结构。该函数会自动处理所有中间目录的创建。
如果路径中的任何目录已存在(没有 exist_ok=True),则会引发 FileExistsError。默认模式 (0o777) 可能会被 umask 修改。
使用 exist_ok 参数
exist_ok 参数可防止目录已存在时出现错误。当为 True 时,如果目标目录存在,它会默默地继续。
import os path = "existing_dir/subdir" # First creation (works) os.makedirs(path) print(f"Created {path}") # Second attempt (fails without exist_ok) try: os.makedirs(path) print("This won't print") except FileExistsError: print(f"{path} already exists") # With exist_ok=True os.makedirs(path, exist_ok=True) print(f"Success with exist_ok=True")
第一次尝试成功,第二次尝试失败并出现 FileExistsError,第三次尝试由于 exist_ok=True 而成功。这对于幂等操作很有用。
请注意,exist_ok 仅在目标目录存在时才阻止错误。其他错误(如权限问题)仍将引发异常。
设置目录权限
mode 参数控制目录权限。在类 Unix 系统上,这会被进程的 umask 修改。此示例显示了权限设置。
import os import stat path = "private_dir" # Create with restrictive permissions (700) os.makedirs(path, mode=0o700) print(f"Created {path} with 700 permissions") # Verify permissions st = os.stat(path) print(f"Actual permissions: {oct(st.st_mode & 0o777)}") # Create with different permissions path2 = "shared_dir" os.makedirs(path2, mode=0o755) print(f"Created {path2} with 755 permissions")
这将创建具有特定权限的目录。第一个目录仅可由所有者访问 (700),第二个目录允许组/其他人读取/执行。
实际权限是 mode & ~umask。如果需要精确的权限,请使用 os.umask() 来控制掩码。
处理符号链接
通过符号链接创建目录时,行为取决于系统。此示例演示了潜在的场景和结果。
import os # Setup: create target and symlink os.makedirs("target_dir") os.symlink("target_dir", "symlink_dir") try: # Attempt to create through symlink os.makedirs("symlink_dir/new_dir") print("Created through symlink") except FileExistsError: print("Failed to create through symlink") # Create a broken symlink os.symlink("nonexistent", "broken_link") try: # Attempt to create through broken symlink os.makedirs("broken_link/new_dir") print("Created through broken link") except OSError as e: print(f"Failed: {e}")
该行为因系统而异。有些遵循符号链接,有些则不遵循。除非创建完整路径,否则断开的链接通常会失败。
为了获得可预测的行为,请在使用 os.path.realpath() 创建目录之前解析链接,或者避免目标路径中的符号链接。
错误处理
os.makedirs
可能会引发多个异常。此示例显示了常见的错误场景和正确的处理技术。
import os import errno paths = [ "/root/protected_dir", # Permission denied "valid/new_dir", # Should work "invalid/chars|here", # Invalid characters "" # Empty path ] for path in paths: try: os.makedirs(path) print(f"Created {path}") except PermissionError: print(f"Permission denied for {path}") except OSError as e: if e.errno == errno.EEXIST: print(f"{path} already exists") elif e.errno == errno.EINVAL: print(f"Invalid path: {path}") else: print(f"Failed to create {path}: {e}")
这演示了处理各种错误情况:权限问题、无效路径和现有目录。特定的 errno 值有助于识别问题。
对于健壮的代码,当您需要为不同的故障模式使用不同的处理方式时,请捕获特定的异常,而不是通用的 OSError。
创建临时目录
将 os.makedirs
与 tempfile 结合使用可创建安全的临时目录结构。此示例显示了一个实际的实现。
import os import tempfile # Create a secure temp directory structure try: temp_root = tempfile.mkdtemp() print(f"Created temp root: {temp_root}") # Create nested structure nested_path = os.path.join(temp_root, "level1", "level2") os.makedirs(nested_path, mode=0o700) print(f"Created nested structure at {nested_path}") # Verify print(os.listdir(os.path.join(temp_root, "level1"))) finally: # Cleanup (in real code, use shutil.rmtree) print(f"Would remove {temp_root} here") # os.rmdir(temp_root) # Would fail with nested content
这将创建一个具有安全权限的临时根目录,然后在其中构建一个嵌套结构。该示例包括清理注意事项。
在生产代码中,使用 tempfile.TemporaryDirectory 或 shutil.rmtree 来正确清理嵌套的临时目录。
Windows 特定的注意事项
- 路径分隔符: Windows 接受 / 和 \
- 权限: Mode 参数的工作方式与 Unix 不同
- 长路径: 对于非常长的路径,可能需要 \\?\ 前缀
- 保留名称: 避免将 CON、PRN 等用作目录名称
- 区分大小写: Windows 路径不区分大小写
最佳实践
- 使用 exist_ok=True: 用于幂等的目录创建
- 设置显式模式: 不要依赖默认权限
- 处理错误: 适当地捕获特定的异常
- 清理: 完成后删除临时目录
- 首选 pathlib: 对于较新的代码,请考虑 Path.mkdir
资料来源
作者
列出所有 Python 教程。