Python os.lstat 函数
上次修改时间:2025 年 4 月 11 日
本综合指南探讨了 Python 的 os.lstat 函数,该函数检索文件状态,而不跟随符号链接。我们将介绍 stat 结构、符号链接处理和实际的文件系统示例。
基本定义
os.lstat 函数返回有关文件的状态信息,而不跟随符号链接。它类似于 os.stat,但在符号链接处理方面有所不同。
关键参数:path(要检查的文件/目录)。返回一个 stat_result 对象,其中包含文件属性,如大小、权限和时间戳。
基本文件信息
此示例演示了如何使用 os.lstat 检索基本文件信息。我们将以人类可读的形式显示文件大小、修改时间和权限。
import os
import time
file_path = "example.txt"
# Get file stats
stats = os.lstat(file_path)
print(f"File: {file_path}")
print(f"Size: {stats.st_size} bytes")
print(f"Last modified: {time.ctime(stats.st_mtime)}")
print(f"Permissions: {oct(stats.st_mode)[-3:]}")
print(f"Owner UID: {stats.st_uid}")
print(f"Group GID: {stats.st_gid}")
该代码检索并显示基本文件元数据。st_size 给出文件大小,st_mtime 显示修改时间,而 st_mode 包含权限位。
请注意,与 os.stat 不同,os.lstat 不会跟随符号链接;os.stat 将返回有关链接文件的信息,而不是链接本身。
检查文件类型
os.lstat 可以使用 st_mode 属性与 os.path 的文件类型检查函数相结合来确定文件类型。此示例显示了各种检查。
import os
import stat
path = "example"
stats = os.lstat(path)
print(f"Checking type of: {path}")
print(f"Is regular file: {stat.S_ISREG(stats.st_mode)}")
print(f"Is directory: {stat.S_ISDIR(stats.st_mode)}")
print(f"Is symbolic link: {stat.S_ISLNK(stats.st_mode)}")
print(f"Is FIFO/pipe: {stat.S_ISFIFO(stats.st_mode)}")
print(f"Is block device: {stat.S_ISBLK(stats.st_mode)}")
print(f"Is character device: {stat.S_ISCHR(stats.st_mode)}")
print(f"Is socket: {stat.S_ISSOCK(stats.st_mode)}")
此代码使用 stat 模块常量来检查各种文件类型。如果文件与该特定类型匹配,则每个 S_IS* 函数都返回 True。
对于符号链接,os.lstat 将把它们显示为链接,而 os.stat 将显示链接文件的类型。
符号链接处理
此示例演示了在使用符号链接时 os.lstat 和 os.stat 之间的区别。我们将创建一个链接并检查这两个函数。
import os
# Create a target file and symbolic link
with open("target.txt", "w") as f:
f.write("Original content")
os.symlink("target.txt", "link.txt")
# Compare lstat and stat
link_stats = os.lstat("link.txt")
target_stats = os.stat("link.txt")
print("Symbolic link info (lstat):")
print(f"Size: {link_stats.st_size}")
print(f"Is link: {os.path.islink('link.txt')}")
print("\nTarget file info (stat):")
print(f"Size: {target_stats.st_size}")
print(f"Is link: {os.path.islink('target.txt')}")
输出显示 os.lstat 返回有关符号链接本身的信息(小尺寸),而 os.stat 遵循该链接以返回有关目标文件的信息。
在 Python 文件操作中使用符号链接时,这种区别至关重要。
文件时间戳
os.lstat 提供三个时间戳值:st_atime(访问时间)、st_mtime(修改时间)和 st_ctime(创建/更改时间)。此示例显示了所有三个。
import os
import time
file_path = "timestamp_example.txt"
# Create file and get initial stats
with open(file_path, "w") as f:
f.write("Initial content")
stats = os.lstat(file_path)
print("Initial timestamps:")
print(f"Access: {time.ctime(stats.st_atime)}")
print(f"Modification: {time.ctime(stats.st_mtime)}")
print(f"Change: {time.ctime(stats.st_ctime)}")
# Modify file and check again
time.sleep(1)
with open(file_path, "a") as f:
f.write("\nAdditional content")
new_stats = os.lstat(file_path)
print("\nAfter modification:")
print(f"Access: {time.ctime(new_stats.st_atime)}")
print(f"Modification: {time.ctime(new_stats.st_mtime)}")
print(f"Change: {time.ctime(new_stats.st_ctime)}")
该示例显示了不同的操作如何影响文件时间戳。写入文件会更新 mtime 和 ctime,而 atime 会跟踪上次访问时间。
注意:st_ctime 在 Unix(元数据更改)和 Windows(创建时间)上具有不同的含义。
文件权限
本示例演示了如何使用来自 os.lstat 的信息和 stat 模块常量来解释和修改文件权限。
import os
import stat
file_path = "permission_test.txt"
# Create file and get permissions
with open(file_path, "w") as f:
f.write("Permission test")
stats = os.lstat(file_path)
# Display current permissions
print(f"Current permissions: {oct(stats.st_mode)[-3:]}")
# Check specific permissions
print("\nPermission checks:")
print(f"Owner readable: {bool(stats.st_mode & stat.S_IRUSR)}")
print(f"Owner writable: {bool(stats.st_mode & stat.S_IWUSR)}")
print(f"Owner executable: {bool(stats.st_mode & stat.S_IXUSR)}")
print(f"Group writable: {bool(stats.st_mode & stat.S_IWGRP)}")
print(f"Others executable: {bool(stats.st_mode & stat.S_IXOTH)}")
# Change permissions
os.chmod(file_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP)
new_stats = os.lstat(file_path)
print(f"\nNew permissions: {oct(new_stats.st_mode)[-3:]}")
该代码显示了如何使用与 stat 模块常量进行按位 AND 运算来检查各个权限位。然后,它演示了如何使用 os.chmod 更改权限。
理解这些权限位对于 Python 应用程序中的安全文件处理至关重要。
比较文件
此示例使用 os.lstat 通过它们的设备/inode 编号来比较两个文件,这比比较路径来检测相同文件更可靠。
import os
def are_same_file(file1, file2):
try:
stat1 = os.lstat(file1)
stat2 = os.lstat(file2)
return (stat1.st_dev == stat2.st_dev and
stat1.st_ino == stat2.st_ino)
except FileNotFoundError:
return False
# Test cases
file_a = "file1.txt"
file_b = "file2.txt"
file_c = "file1.txt" # Hard link to file_a
# Create test files
with open(file_a, "w") as f:
f.write("Content")
os.link(file_a, file_c) # Create hard link
with open(file_b, "w") as f:
f.write("Content")
print(f"Same file (a vs b): {are_same_file(file_a, file_b)}")
print(f"Same file (a vs c): {are_same_file(file_a, file_c)}")
print(f"Same file (b vs c): {are_same_file(file_b, file_c)}")
该函数比较设备(st_dev)和 inode(st_ino)编号,以确定两个路径是否引用同一个物理文件,即使它们是硬链接。
与简单的路径比较不同,此方法适用于不同的目录位置和硬链接。
安全注意事项
- 符号链接: os.lstat 不会跟随它们,从而防止符号链接攻击
- TOCTOU 风险: 文件状态可能在 lstat 和使用之间发生变化
- 权限检查: 始终在敏感操作之前进行验证
- 错误处理: 处理缺少文件的 FileNotFoundError
- 跨平台: 某些属性在 Unix 和 Windows 之间有所不同
最佳实践
- 用于链接: 在使用符号链接时,首选 lstat
- 与 stat 结合使用: 需要完整的文件信息时,同时使用两者
- 检查错误: 处理缺少文件的异常
- 谨慎缓存: 文件信息可能在检查之间发生变化
- 记录假设: 记录何时需要链接与目标信息
资料来源
作者
列出所有 Python 教程。