ZetCode

Python os.lstat 函数

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

本综合指南探讨了 Python 的 os.lstat 函数,该函数检索文件状态,而不跟随符号链接。我们将介绍 stat 结构、符号链接处理和实际的文件系统示例。

基本定义

os.lstat 函数返回有关文件的状态信息,而不跟随符号链接。它类似于 os.stat,但在符号链接处理方面有所不同。

关键参数:path(要检查的文件/目录)。返回一个 stat_result 对象,其中包含文件属性,如大小、权限和时间戳。

基本文件信息

此示例演示了如何使用 os.lstat 检索基本文件信息。我们将以人类可读的形式显示文件大小、修改时间和权限。

basic_info.py
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 的文件类型检查函数相结合来确定文件类型。此示例显示了各种检查。

file_type.py
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 之间的区别。我们将创建一个链接并检查这两个函数。

symlink_diff.py
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(创建/更改时间)。此示例显示了所有三个。

timestamps.py
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 模块常量来解释和修改文件权限。

permissions.py
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 编号来比较两个文件,这比比较路径来检测相同文件更可靠。

file_comparison.py
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)编号,以确定两个路径是否引用同一个物理文件,即使它们是硬链接。

与简单的路径比较不同,此方法适用于不同的目录位置和硬链接。

安全注意事项

最佳实践

资料来源

作者

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

列出所有 Python 教程