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