ZetCode

Python os.chmod 函数

上次修改时间:2025 年 4 月 11 日

本综合指南探讨了 Python 的 os.chmod 函数,该函数用于更改文件模式位(权限)。我们将介绍权限标志、符号模式与数字模式,以及实际的权限管理示例。

基本定义

os.chmod 函数更改文件或目录的模式(权限)。 它遵循 Unix 风格的权限位,并且也适用于 Windows。

主要参数:path(要修改的文件/目录),mode(权限标志:stat.S_IRWXU、stat.S_IRUSR 等或八进制数,如 0o755)。 返回 None。

设置基本文件权限

此示例演示了如何使用八进制表示法为文件设置基本的读取、写入和执行权限。 八进制数表示权限位。

basic_permissions.py
import os

file_path = "document.txt"

# Create file if it doesn't exist
if not os.path.exists(file_path):
    with open(file_path, "w") as f:
        f.write("Sample content")

# Set permissions to read/write for owner, read for others
os.chmod(file_path, 0o644)
print(f"Set permissions for {file_path} to 644 (rw-r--r--)")

# Verify permissions
mode = os.stat(file_path).st_mode
print(f"Current permissions: {oct(mode)[-3:]}")

这将设置所有者读/写 (6)、组读 (4) 和其他读 (4) 权限。 0o 前缀表示 Python 中的八进制表示法。 最后一个打印语句显示模式。

八进制表示法很紧凑,但可能不如符号常量易读。 下面的示例将展示替代方法。

使用 stat 模块常量

stat 模块为权限位提供了符号常量,使代码更具可读性。 此示例使用按位 OR 运算将它们组合在一起。

stat_constants.py
import os
import stat

file_path = "script.sh"

# Create executable script
with open(file_path, "w") as f:
    f.write("#!/bin/bash\necho 'Hello World'")

# Set permissions: rwxr-xr-x
os.chmod(file_path, 
    stat.S_IRWXU |  # User read, write, execute
    stat.S_IRGRP |  # Group read
    stat.S_IXGRP |  # Group execute
    stat.S_IROTH |  # Others read
    stat.S_IXOTH    # Others execute
)

print(f"Made {file_path} executable for all")
print(f"Current permissions: {oct(os.stat(file_path).st_mode)[-3:]}")

这将为所有者设置完全权限 (rwx),为组设置读/执行权限 (r-x),为其他用户设置读/执行权限 (r-x)。 符号常量使意图清晰。

stat 常量可以灵活组合,以创建应用程序所需的任何权限组合。

更改目录权限

目录权限的工作方式与文件类似,但含义不同。 目录上的执行权限允许遍历/搜索它们。

directory_permissions.py
import os
import stat

dir_path = "private_data"

# Create directory if it doesn't exist
if not os.path.exists(dir_path):
    os.mkdir(dir_path)

# Restrict directory to owner only (rwx------)
os.chmod(dir_path, stat.S_IRWXU)

print(f"Set strict permissions for {dir_path}")
print(f"Current permissions: {oct(os.stat(dir_path).st_mode)[-3:]}")

# Verify access
try:
    os.listdir(dir_path)
    print("Can access directory (running as owner)")
except PermissionError:
    print("Cannot access directory")

这将目录权限设置为 rwx------ (700),仅允许所有者访问。 其他用户无法列出或进入目录。

目录权限对于存储敏感数据时的安全性至关重要。 它们控制谁可以访问目录中的文件。

修改特定权限位

您可以通过先读取当前模式,然后应用更改来修改特定权限位,同时保留其他权限位。 这种方法更精确。

modify_bits.py
import os
import stat

file_path = "config.cfg"

# Create file with default permissions
with open(file_path, "w") as f:
    f.write("key=value")

# Get current permissions
current_mode = os.stat(file_path).st_mode

# Add group write permission
new_mode = current_mode | stat.S_IWGRP
os.chmod(file_path, new_mode)

print(f"Added group write permission to {file_path}")
print(f"New permissions: {oct(os.stat(file_path).st_mode)[-3:]}")

# Remove others read permission
new_mode = new_mode & ~stat.S_IROTH
os.chmod(file_path, new_mode)

print(f"Removed others read permission")
print(f"Final permissions: {oct(os.stat(file_path).st_mode)[-3:]}")

这首先使用按位 OR 添加组写权限,然后使用按位 AND 与权限位的补码来删除其他用户读权限。

当您需要修改特定权限而不影响其他现有权限位时,此方法非常有用。

处理符号权限

虽然 Python 没有内置的符号权限表示法(如 chmod u+x),但我们可以创建一个辅助函数来解析此类表达式。

symbolic_permissions.py
import os
import stat

def apply_symbolic_chmod(path, symbolic):
    """Apply symbolic permissions like chmod command"""
    current = os.stat(path).st_mode
    who, op, perms = symbolic[:1], symbolic[1:2], symbolic[2:]
    
    # Determine which bits to modify
    mask = 0
    if 'u' in who or 'a' in who:
        mask |= stat.S_IRWXU
    if 'g' in who or 'a' in who:
        mask |= stat.S_IRWXG
    if 'o' in who or 'a' in who:
        mask |= stat.S_IRWXO
    
    # Determine new permissions
    new_bits = 0
    if 'r' in perms:
        new_bits |= (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
    if 'w' in perms:
        new_bits |= (stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH)
    if 'x' in perms:
        new_bits |= (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
    
    # Apply operation
    if op == '+':
        new_mode = current | (new_bits & mask)
    elif op == '-':
        new_mode = current & ~(new_bits & mask)
    elif op == '=':
        new_mode = (current & ~mask) | (new_bits & mask)
    
    os.chmod(path, new_mode)

file_path = "app.log"
with open(file_path, "w") as f:
    f.write("Log entries...")

# Examples of symbolic notation
apply_symbolic_chmod(file_path, "u=rw")  # User read/write
apply_symbolic_chmod(file_path, "go-r")  # Remove group/others read
apply_symbolic_chmod(file_path, "a+x")   # Add execute for all

print(f"Final permissions: {oct(os.stat(file_path).st_mode)[-3:]}")

这实现了一个基本的符号权限解析器,类似于 Unix chmod。 它处理谁 (u/g/o/a)、操作 (+/-/=) 和权限 (r/w/x)。

虽然不如 Unix 命令完整,但它演示了如何在需要时在 Python 中实现符号权限更改。

Windows 兼容性说明

在 Windows 上,只有某些权限位是有意义的。 此示例显示了在 Windows 系统上哪些有效,哪些无效。

windows_permissions.py
import os
import stat
import sys

file_path = "winfile.txt"

with open(file_path, "w") as f:
    f.write("Windows test")

# These work on Windows
os.chmod(file_path, stat.S_IREAD)   # Read-only
os.chmod(file_path, stat.S_IWRITE)  # Write-only
os.chmod(file_path, stat.S_IREAD | stat.S_IWRITE)  # Read/write

print("Basic permission changes work on Windows")

# These are ignored on Windows
try:
    os.chmod(file_path, stat.S_IXUSR)  # Execute
    print("Execute bit set (but ignored on Windows)")
except:
    print("Execute bit not supported")

if sys.platform == "win32":
    print("\nNote: Windows has limited permission support")
    print("Only read-only/writeable flags are effective")

Windows 仅遵守只读标志(对应于 S_IREAD)。 其他权限位可能会被存储,但不会影响文件访问。

在编写跨平台代码时,请在所有目标平台上测试权限更改,以确保行为一致。

安全注意事项

最佳实践

资料来源

作者

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

列出所有 Python 教程