candplus
candplus
发布于 3个月前

python – shutil.disk_usage()中的差异

我正在使用shutil.disk_usage()函数来查找特定路径的当前磁盘使用情况(可用,使用的数量等).据我所知,这是os.statvfs()调用的包装器.我发现它没有给出我期望的答案,与Linux中“du”的输出相比.

出于公司隐私原因,我已经模糊了下面的一些路径,但输出和代码在其他方面都没有被删除.我使用的是Python 3.3.2 64位版本.

#!/apps/python/3.3.2_64bit/bin/python3

# test of shutils.diskusage module
import shutil

BytesPerGB = 1024 * 1024 * 1024

(total, used, free) = shutil.disk_usage("/data/foo/")
print ("Total: %.2fGB" % (float(total)/BytesPerGB))
print ("Used:  %.2fGB" % (float(used)/BytesPerGB))

(total1, used1, free1) = shutil.disk_usage("/data/foo/utils/")
print ("Total: %.2fGB" % (float(total1)/BytesPerGB))
print ("Used:  %.2fGB" % (float(used1)/BytesPerGB))

哪个输出:

/data/foo/drivecode/me % disk_usage_test.py
Total: 609.60GB
Used:  291.58GB
Total: 609.60GB
Used:  291.58GB

正如您所看到的,主要问题是我希望“Used”的第二个数量要小得多,因为它是第一个目录的子集.

/data/foo/drivecode/me % du -sh /data/foo/utils
2.0G    /data/foo/utils

尽管我信任“du”,但我发现很难相信Python模块也不正确.所以也许只是我对Linux文件系统的理解可能是个问题. ?

我写了一个模块(很大程度上基于SO的某人的代码),它递归地获取了disk_usage,直到现在我才使用它.它看起来与“du”输出相匹配但是很多,比shutil.disk_usage()函数慢得多,所以我希望我可以使那个工作.

非常感谢提前.

解决方案:

问题是shutil使用下面的statvfs系统调用来确定使用的空间.据我所知,此系统调用没有文件路径粒度,只有文件系统粒度.这意味着您提供的路径仅有助于识别要查询的文件系统,而不是路径. 换句话说,你给它路径/ data / foo / utils然后它确定了哪个文件系统支持这个文件路径.然后它查询文件系统.当您考虑如何在shutil中定义used参数时,这一点就变得很明显了:

used = (st.f_blocks - st.f_bfree) * st.f_frsize

哪里:

fsblkcnt_t     f_blocks;   /* size of fs in f_frsize units */
fsblkcnt_t     f_bfree;    /* # free blocks */
unsigned long  f_frsize;   /* fragment size */

这就是它为您提供整个文件系统使用的总空间的原因.

实际上,在我看来,du命令本身也会遍历文件结构并增加文件大小.这是GNU coreutils du命令的source code.