Python 获取文件大小:高效、准确的实践指南74
在日常的软件开发和系统管理中,获取文件的大小是一项非常基础且常见的任务。无论是为了监控磁盘空间、显示文件下载进度、验证文件完整性,还是仅仅为了做数据统计,准确地获取文件大小都是至关重要的。Python 作为一种功能强大且易于使用的编程语言,提供了多种灵活的方法来实现这一目标。本文将作为一份专业的实践指南,深入探讨 Python 中获取文件大小的各种方法,并讨论其适用场景、优缺点、以及在实际应用中需要注意的各种细节。
一、最直接的方法:使用 `()`
对于大多数场景,Python 标准库中的 `()` 函数是最简洁、最直接获取文件大小的方法。它返回文件的大小(以字节为单位)。
这个函数位于 `os` 模块的 `path` 子模块中,专门用于处理文件路径相关的操作。
工作原理与示例
(path) 接收一个文件路径作为参数,并返回一个整数,表示文件的大小(字节数)。如果文件不存在,它会抛出 `FileNotFoundError` 异常。import os
def get_file_size_os_path(file_path):
"""
使用 获取文件大小。
"""
try:
size = (file_path)
print(f"文件 '{file_path}' 的大小为:{size} 字节")
return size
except FileNotFoundError:
print(f"错误:文件 '{file_path}' 未找到。")
return -1
except PermissionError:
print(f"错误:没有权限访问文件 '{file_path}'。")
return -1
except Exception as e:
print(f"发生未知错误:{e}")
return -1
# 示例使用
file1 = ""
file2 = "" # 不存在的文件
file3 = "" # 假设存在一个大文件
# 创建一个示例文件
with open(file1, "w", encoding="utf-8") as f:
("Hello, Python!")
("This is a test file for getting its size.")
get_file_size_os_path(file1)
get_file_size_os_path(file2)
# 清理示例文件
(file1)
特点与适用场景
简洁高效: 它是获取文件大小最直接、最易读的方法。
跨平台: os 模块是 Python 标准库的一部分,() 在所有支持的操作系统上都能正常工作。
返回字节: 返回值始终是文件的字节数,这在进行精确计算时非常有用。
错误处理: 需要显式处理 FileNotFoundError 和 PermissionError 等异常,以增强程序的健壮性。
二、获取更丰富的文件信息:使用 `()`
除了文件大小,有时我们还需要获取文件的其他元数据,例如创建时间、修改时间、访问时间、文件权限等。`()` 函数就是为此而生。它返回一个 `stat_result` 对象,其中包含了文件的所有这些详细信息,当然也包括文件大小。
工作原理与示例
(path) 接收一个文件路径,并返回一个 `stat_result` 对象。文件大小信息存储在该对象的 `st_size` 属性中。import os
import datetime
def get_file_info_os_stat(file_path):
"""
使用 获取文件大小及其他信息。
"""
try:
stat_info = (file_path)
print(f"文件 '{file_path}' 的详细信息:")
print(f" 大小:{stat_info.st_size} 字节")
print(f" 最后修改时间:{(stat_info.st_mtime)}")
print(f" 最后访问时间:{(stat_info.st_atime)}")
print(f" 创建时间:{(stat_info.st_ctime)}") # Windows/Unix有所不同
print(f" 文件模式(权限):{oct(stat_info.st_mode)}")
print(f" 设备ID:{stat_info.st_dev}")
print(f" inode号:{stat_info.st_ino}")
return stat_info.st_size
except FileNotFoundError:
print(f"错误:文件 '{file_path}' 未找到。")
return -1
except PermissionError:
print(f"错误:没有权限访问文件 '{file_path}'。")
return -1
except Exception as e:
print(f"发生未知错误:{e}")
return -1
# 示例使用
file_stat_test = ""
with open(file_stat_test, "w", encoding="utf-8") as f:
("This file is for testing .")
("It contains multiple lines.")
get_file_info_os_stat(file_stat_test)
# 清理示例文件
(file_stat_test)
特点与适用场景
信息丰富: 除了大小,还能获取文件的其他元数据,避免了多次系统调用。
性能略高: 如果同时需要多个文件属性,使用 () 一次性获取比多次调用不同 函数更高效。
跨平台: 同样是标准库函数,具有良好的跨平台兼容性。
返回字节: st_size 属性返回文件大小,单位也是字节。
错误处理: 同样需要处理 FileNotFoundError 和 PermissionError。
三、现代化的路径操作:`pathlib` 模块
从 Python 3.4 开始,`pathlib` 模块为文件系统路径操作提供了面向对象的接口,使得代码更具可读性和可维护性。使用 `pathlib` 获取文件大小同样非常优雅。
工作原理与示例
首先,你需要创建一个 `Path` 对象来表示文件路径,然后调用其 `stat()` 方法,这将返回一个与 `()` 相同的 `stat_result` 对象。文件大小信息同样通过 `st_size` 属性获取。from pathlib import Path
import datetime
def get_file_size_pathlib(file_path_str):
"""
使用 pathlib 获取文件大小及其他信息。
"""
file_path = Path(file_path_str) # 创建 Path 对象
try:
stat_info = () # 调用 stat() 方法
print(f"使用 pathlib 获取文件 '{file_path}' 的信息:")
print(f" 大小:{stat_info.st_size} 字节")
print(f" 最后修改时间:{(stat_info.st_mtime)}")
return stat_info.st_size
except FileNotFoundError:
print(f"错误:文件 '{file_path}' 未找到。")
return -1
except PermissionError:
print(f"错误:没有权限访问文件 '{file_path}'。")
return -1
except Exception as e:
print(f"发生未知错误:{e}")
return -1
# 示例使用
pathlib_test_file = ""
with open(pathlib_test_file, "w", encoding="utf-8") as f:
("This is a log entry.")
("Another line for pathlib demo.")
get_file_size_pathlib(pathlib_test_file)
# 清理示例文件
(pathlib_test_file)
特点与适用场景
面向对象: 提供了更直观、更链式的路径操作方式,代码更易于理解和编写。
可读性高: 相较于字符串拼接和 函数,pathlib 的语法更自然。
功能强大: 除了 stat(),还提供了创建、删除、移动文件/目录等丰富的方法。
推荐使用: 在 Python 3.4+ 的新项目中,pathlib 是处理文件路径的推荐方式。
返回字节: 同样通过 st_size 属性获取字节数。
错误处理: 同样需要处理 FileNotFoundError 和 PermissionError。
四、文件大小单位转换与可读性
虽然上述方法都返回文件在系统中的原始字节数,但对于人类阅读来说,字节数往往不够直观。将字节数转换为更高级的单位(KB、MB、GB、TB)可以大大提高可读性。
实现一个单位转换函数
def human_readable_size(size_bytes):
"""
将文件大小(字节)转换为人类可读的格式。
"""
if size_bytes < 0:
return "无效大小"
units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
unit_index = 0
while size_bytes >= 1024 and unit_index < len(units) - 1:
size_bytes /= 1024.0
unit_index += 1
return f"{size_bytes:.2f} {units[unit_index]}"
# 结合前面的函数进行演示
print("--- 结合单位转换函数演示 ---")
file_for_conversion = ""
# 创建一个约 1.5MB 的文件
with open(file_for_conversion, "wb") as f:
(1.5 * 1024 * 1024 - 1) # 定位到文件末尾 - 1
(b'\0') # 写入一个字节以确保文件大小
size_in_bytes = get_file_size_os_path(file_for_conversion)
if size_in_bytes != -1:
print(f"人类可读大小:{human_readable_size(size_in_bytes)}")
# 清理示例文件
(file_for_conversion)
# 其他示例
print(f"100 Bytes: {human_readable_size(100)}")
print(f"1024 Bytes: {human_readable_size(1024)}")
print(f"1048576 Bytes (1MB): {human_readable_size(1048576)}")
print(f"1073741824 Bytes (1GB): {human_readable_size(1073741824)}")
print(f"1.5 GB: {human_readable_size(1.5 * 1024 * 1024 * 1024)}")
这个函数通过循环除以 1024,并将单位索引递增,直到找到合适的单位,从而将字节数转换为带有两个小数点的可读字符串。
五、处理特殊情况与注意事项
1. 文件不存在与权限问题
如前所述,所有获取文件大小的方法都可能遇到 `FileNotFoundError` (文件不存在) 或 `PermissionError` (权限不足) 异常。在生产代码中,务必使用 `try-except` 块来捕获并妥善处理这些异常,以防止程序崩溃。
2. 符号链接 (Symbolic Links)
在 Linux/Unix 系统中,文件可以是符号链接(软链接)。
`()` 和 `()` (以及 `().stat()`) 默认会跟随符号链接,返回目标文件的大小。
如果你需要获取符号链接本身的大小(通常很小,存储的是目标路径的字符串),可以使用 `(link_path, follow_symlinks=False)`(Python 3.6+)或 `()` (以及 `().lstat()`)。`lstat()` 返回的是链接文件本身的 `stat_result` 对象。
import os
from pathlib import Path
# 创建一个示例文件
with open("", "w") as f:
("This is the content of the target file.")
# 创建一个指向它的符号链接
if == 'posix': # 仅在类Unix系统上创建符号链接
try:
("", "")
print("--- 符号链接处理 ---")
# 默认行为:跟随链接
print(f"(''): {('')} Bytes")
print(f"Path('').stat().st_size: {Path('').stat().st_size} Bytes")
# 获取链接文件本身的大小 ( 或 (follow_symlinks=False))
print(f"('').st_size: {('').st_size} Bytes")
# Python 3.6+
# print(f"('', follow_symlinks=False): {('', follow_symlinks=False)} Bytes")
("") # 清理链接
except OSError as e:
print(f"无法创建符号链接或不支持:{e}")
("") # 清理目标文件
3. 目录大小的计算
重要提示: `()`、`().st_size` 和 `().stat().st_size` 不适用于目录。对于目录,它们通常会返回一个平台特定的值(例如,在 Linux 上可能是 4096 字节,代表目录条目的大小),这个值不是目录中所有文件大小的总和。
要获取目录的实际占用空间(包括所有子文件和子目录),你需要递归地遍历目录结构,并累加所有文件的大小。import os
from pathlib import Path
def get_directory_size(directory_path):
"""
递归计算目录中所有文件的大小总和。
"""
total_size = 0
if not (directory_path):
print(f"错误:'{directory_path}' 不是一个有效的目录。")
return -1
print(f"正在计算目录 '{directory_path}' 的大小...")
for dirpath, dirnames, filenames in (directory_path):
for f in filenames:
file_path = Path(dirpath) / f # 使用 pathlib 拼接路径
try:
# 排除符号链接本身的大小,只计算实际文件内容
if file_path.is_symlink():
total_size += ().stat().st_size # 获取链接目标的大小
else:
total_size += ().st_size
except FileNotFoundError:
print(f"警告:文件 '{file_path}' 未找到,可能已被删除。跳过。")
except PermissionError:
print(f"警告:没有权限访问文件 '{file_path}'。跳过。")
except Exception as e:
print(f"警告:处理文件 '{file_path}' 时发生错误:{e}。跳过。")
return total_size
# 示例使用:创建一个包含文件和子目录的复杂结构
test_dir = "my_test_directory"
sub_dir1 = Path(test_dir) / "sub_dir_a"
sub_dir2 = Path(test_dir) / "sub_dir_b"
(sub_dir1, exist_ok=True)
(sub_dir2, exist_ok=True)
with open(Path(test_dir) / "", "w") as f:
("content of file1") # 16 bytes
with open(sub_dir1 / "", "w") as f:
("content of file2 a little longer") # 32 bytes
with open(sub_dir2 / "", "w") as f:
("content of file3 very longgggggggggggggggggggggggggggggggggg") # 60 bytes
total_dir_size = get_directory_size(test_dir)
if total_dir_size != -1:
print(f"目录 '{test_dir}' 的总大小为:{total_dir_size} 字节 ({human_readable_size(total_dir_size)})")
# 期望大小:16 + 32 + 60 = 108 bytes
# 清理测试目录
import shutil
(test_dir)
上述 `get_directory_size` 函数使用 `()` 遍历目录树,并对每个找到的文件累加其大小。这是计算目录总大小的标准方法。
六、性能考量
对于大多数应用场景,上述获取单个文件大小的方法(`()`, `()`, `().stat()`) 的性能差异可以忽略不计,它们都是对底层操作系统 API 的直接调用。主要的性能开销在于文件系统 I/O本身。
如果需要处理成千上万个文件,或者在性能敏感的应用中,以下几点值得考虑:
批量操作: 避免在循环中重复打开和关闭文件,如果可能,一次性获取多个文件的信息。但对于文件大小,每次调用都相对独立,此点帮助不大。
并发处理: 对于大量文件,可以考虑使用多线程或多进程并发处理文件列表,因为文件 I/O 操作通常是瓶颈,可以利用系统的多核能力或非阻塞 I/O。
缓存: 如果文件大小信息不经常变化,并且会被频繁查询,可以考虑将结果缓存起来,减少对文件系统的访问。
Python 提供了多种灵活、高效且易于使用的方法来获取文件大小。根据你的具体需求,可以选择最适合的方法:
如果你只需要文件大小,并且代码越简洁越好,() 是最佳选择。
如果你需要文件大小以及其他文件元数据(如修改时间、创建时间),使用 () 或 ().stat() 可以一次性获取所有信息,避免多次系统调用。推荐使用 pathlib 模块,因为它提供了更现代、面向对象的路径操作方式。
对于目录大小的计算,你需要使用 () 递归遍历目录,并累加所有文件的尺寸。
无论选择哪种方法,始终要牢记处理文件不存在(FileNotFoundError)和权限问题(PermissionError)的异常,以确保程序的健壮性。同时,通过将原始字节数转换为人类可读的格式,可以显著提升用户体验。
2025-10-12
C语言打印图形:从实心到空心正方形的输出详解与技巧
https://www.shuihudhg.cn/132881.html
PHP数据库记录数统计完全攻略:MySQLi、PDO与性能优化实战
https://www.shuihudhg.cn/132880.html
PHP数据库交互:从基础查询到安全编辑的全面指南
https://www.shuihudhg.cn/132879.html
Python文件存在性判断:与pathlib的全面解析
https://www.shuihudhg.cn/132878.html
PHP 处理 HTTP POST 请求:从基础到高级的安全实践与最佳策略
https://www.shuihudhg.cn/132877.html
热门文章
Python 格式化字符串
https://www.shuihudhg.cn/1272.html
Python 函数库:强大的工具箱,提升编程效率
https://www.shuihudhg.cn/3366.html
Python向CSV文件写入数据
https://www.shuihudhg.cn/372.html
Python 静态代码分析:提升代码质量的利器
https://www.shuihudhg.cn/4753.html
Python 文件名命名规范:最佳实践
https://www.shuihudhg.cn/5836.html