ZetCode

Python os.access 函数

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

本综合指南探讨了 Python 的 os.access 函数,该函数用于测试路径的可访问性和权限。我们将介绍权限标志、有效 ID 与实际 ID,以及实用的文件系统测试示例。

基本定义

os.access 函数检查调用用户是否具有指定路径的访问权限。它使用实际的 UID/GID,而不是有效的 ID。

主要参数:path(要检查的文件/目录),mode(权限标志:F_OK、R_OK、W_OK、X_OK)。如果允许访问,则返回 True,否则返回 False。

检查文件是否存在

os.access 最简单的用法是使用 F_OK 模式标志验证文件是否存在。这类似于 os.path.exists,但底层实现不同。

file_exists.py
import os

# Check if file exists
file_path = "example.txt"
if os.access(file_path, os.F_OK):
    print(f"{file_path} exists")
else:
    print(f"{file_path} does not exist")

# Create file if it doesn't exist
if not os.access(file_path, os.F_OK):
    with open(file_path, "w") as f:
        f.write("Hello World")
    print(f"Created {file_path}")

此示例首先检查文件是否存在,然后如果文件不存在则创建它。请注意,在检查和创建之间,文件状态可能会更改 (TOCTOU)。

在大多数情况下,直接尝试操作(如打开)并处理异常比这种两步方法更可取。

测试读取权限

R_OK 模式测试当前用户是否可以读取文件。这会检查文件权限和父目录遍历权限。

read_permission.py
import os

file_path = "data.txt"

# Check read permission
if os.access(file_path, os.R_OK):
    print(f"Can read {file_path}")
    with open(file_path) as f:
        print(f.read())
else:
    print(f"Cannot read {file_path}")

# Alternative approach using try/except
try:
    with open(file_path) as f:
        print(f.read())
except PermissionError:
    print(f"Permission denied for {file_path}")
except FileNotFoundError:
    print(f"{file_path} not found")

第一种方法使用 os.access 在读取之前检查权限。第二种方法显示 EAFP(请求原谅比请求许可更容易)的风格。

EAFP 方法通常在 Python 中更受欢迎,因为它避免了检查和操作之间的竞争条件。

测试写入权限

W_OK 模式验证文件是否可写。对于目录,它检查是否可以创建文件。此示例演示了这两种情况。

write_permission.py
import os

file_path = "output.log"
dir_path = "logs"

# Check file write permission
if os.access(file_path, os.W_OK):
    print(f"Can write to {file_path}")
else:
    print(f"Cannot write to {file_path}")

# Check directory write permission
if os.access(dir_path, os.W_OK):
    print(f"Can create files in {dir_path}")
    new_file = os.path.join(dir_path, "new.log")
    with open(new_file, "w") as f:
        f.write("Log entry")
else:
    print(f"Cannot create files in {dir_path}")

这会检查文件和目录的写入权限。对于目录,W_OK 表示可以创建新文件,而不是可以修改现有文件。

请记住,由于系统更改,权限检查在检查和实际写入操作之间可能会失效。

测试执行权限

X_OK 模式检查执行/搜索权限。对于文件,这意味着可执行二进制文件。对于目录,这意味着遍历/搜索权限。

execute_permission.py
import os

script_path = "myscript.sh"
dir_path = "/usr/local/bin"

# Check file execute permission
if os.access(script_path, os.X_OK):
    print(f"Can execute {script_path}")
    os.system(f"./{script_path}")
else:
    print(f"Cannot execute {script_path}")

# Check directory search permission
if os.access(dir_path, os.X_OK):
    print(f"Can access {dir_path}")
    print(os.listdir(dir_path))
else:
    print(f"Cannot access {dir_path}")

第一部分检查脚本是否可执行。第二部分验证目录遍历权限,这是列出目录内容所必需的。

目录的执行权限与读取权限是分开的 - 您需要同时具备两者才能列出和访问内容。

组合权限标志

可以使用按位或 (|) 组合多个权限标志,以便一次测试多个权限。这比多次单独调用更有效。

combined_permissions.py
import os

file_path = "config.json"

# Check read and write permissions
if os.access(file_path, os.R_OK | os.W_OK):
    print(f"Can read and write {file_path}")
    with open(file_path, "r+") as f:
        data = f.read()
        f.seek(0)
        f.write(data.upper())
else:
    print(f"Missing required permissions for {file_path}")

# Check all permissions
all_perms = os.F_OK | os.R_OK | os.W_OK | os.X_OK
if os.access(file_path, all_perms):
    print(f"Has full access to {file_path}")
else:
    print(f"Doesn't have full access to {file_path}")

第一个检查组合了读取和写入权限。第二个演示了使用按位或运算一次检查所有可能的权限。

组合标志减少了系统调用和单独权限检查之间潜在的竞争条件。

实际 ID 与有效 ID

os.access 使用实际的 UID/GID,而不是有效的 ID。此示例通过临时删除权限来演示差异。

real_vs_effective.py
import os
import pwd

def show_ids():
    print(f"Real UID: {os.getuid()}, Effective UID: {os.geteuid()}")
    print(f"Real GID: {os.getgid()}, Effective GID: {os.getegid()}")

file_path = "/root/.bashrc"

print("Before privilege drop:")
show_ids()
print(f"Accessible: {os.access(file_path, os.R_OK)}")

# Temporarily drop privileges
os.seteuid(os.getuid())

print("\nAfter privilege drop:")
show_ids()
print(f"Accessible: {os.access(file_path, os.R_OK)}")

# Restore privileges
os.seteuid(0)

此脚本显示了当有效 UID 更改时,os.access 的行为与实际操作的不同之处。它需要 root 权限才能完全演示。

关键在于 os.access 基于实际用户进行检查,而实际文件操作使用有效的用户权限。

安全注意事项

最佳实践

资料来源

作者

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

列出所有 Python 教程