You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

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

火山引擎 最新活动