ZetCode

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 最简单的用法是创建单个目录或嵌套目录结构。此示例演示了这两种情况。

basic_creation.py
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 时,如果目标目录存在,它会默默地继续。

exist_ok.py
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 修改。此示例显示了权限设置。

permissions.py
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() 来控制掩码。

处理符号链接

通过符号链接创建目录时,行为取决于系统。此示例演示了潜在的场景和结果。

symlinks.py
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 可能会引发多个异常。此示例显示了常见的错误场景和正确的处理技术。

error_handling.py
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 结合使用可创建安全的临时目录结构。此示例显示了一个实际的实现。

temp_dirs.py
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 特定的注意事项

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程