Python:不打开文件获取文件大小及批量大文件高效方案问询
Python: 获取文件大小无需打开文件的细节与批量优化方案
关于os.stat和os.path.getsize是否会打开文件?
绝对不会!这两个方法都是直接从文件系统的元数据(比如Unix下的inode、Windows下的MFT记录)中读取文件大小,完全不需要打开或关闭文件。
os.path.getsize(path)其实是一个封装函数,底层就是调用os.stat(path).st_size,所以两者本质是一回事。- 你可以放心用它们,不会占用文件句柄,也不会对文件内容做任何读写操作,速度非常快——毕竟只是读个元数据而已。
举个简单的例子:
import os # 两种方式等价 size1 = os.path.getsize("/large/file.tb") size2 = os.stat("/large/file.tb").st_size print(size1 == size2) # 输出 True
扫描TB级文件时,批量获取大小的更快方法?
当你要处理海量文件时,减少系统调用次数是关键。我之前处理过PB级存储的扫描任务,下面这几个方案是实战验证过的高效手段:
1. 用os.scandir()代替os.listdir()/os.walk()
os.scandir()是Python 3.5+引入的,它在遍历目录时会一次性获取文件的大部分元数据(包括大小、修改时间等),而不是像os.listdir()那样只拿到文件名,再逐个调用stat去查大小——这能减少90%以上的系统调用,速度提升非常明显。
如果是Python 3.10+,还可以直接用entry.filesize属性,连stat()都不用调用:
import os total_size = 0 with os.scandir("/path/to/large/directory") as entries: for entry in entries: if entry.is_file(follow_symlinks=False): # Python 3.10+ 直接用entry.filesize # total_size += entry.filesize # 兼容旧版本用这个 total_size += entry.stat().st_size print(f"Total size: {total_size / (1024**4):.2f} TB")
如果需要递归遍历子目录,os.walk()在Python 3.5+已经默认用scandir实现了,但如果你需要更精细的控制(比如跳过某些目录),直接用scandir递归会更高效。
2. 避免不必要的操作
- 跳过符号链接:用
is_file(follow_symlinks=False)避免跟着链接跑,节省时间。 - 不要重复获取元数据:比如如果你已经用
scandir拿到了entry,就不要再单独调用os.path.getsize(),直接用entry里的信息。
3. 关于多进程/多线程的注意事项
很多人会想到用多进程加速,但实际在文件系统扫描时,瓶颈通常在磁盘IO或文件系统的元数据读取速度,而不是CPU。所以多进程往往不会带来明显提升,反而可能因为进程间竞争导致速度变慢。除非你是在分布式存储系统上(比如多个挂载点),可以考虑分目录并行处理。
内容的提问来源于stack exchange,提问作者Ross




