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 教程。