很快得到文件夹的总大小

我想快速find使用Python的任何文件夹的总大小。

import os from os.path import join, getsize, isfile, isdir, splitext def GetFolderSize(path): TotalSize = 0 for item in os.walk(path): for file in item[2]: try: TotalSize = TotalSize + getsize(join(item[0], file)) except: print("error with file: " + join(item[0], file)) return TotalSize print(float(GetFolderSize("C:\\")) /1024 /1024 /1024) 

这是我写的简单的脚本来获取文件夹的总大小,大约需要60秒(+ -5秒)。 通过使用多处理,我把它在四核机器上减less到23秒。

使用Windows文件浏览器只需要约3秒钟(右键单击属性以查看自己)。 那么有没有更快的方式来find一个文件夹的总大小接近的速度,Windows可以做到这一点?

Windows 7中,python2.6(search,但大多数时候人们使用了一个非常类似的方法我自己)先谢谢了。

你处于劣势

Windows资源pipe理器几乎肯定使用FindFirstFile / FindNextFile来遍历目录结构通过一次传递收集大小信息(通过lpFindFileData ),从而使每个文件本质上是一个单一的系统调用。

不幸的是,在这种情况下Python不是你的朋友。 从而,

  1. os.walk 首先调用os.listdir (内部调用FindFirstFile / FindNextFile
    • 从这一点开始的任何额外的系统调用只能使你比Windows资源pipe理器
  2. os.walk 然后调用 os.listdir (内部调用GetFileAttributesEx – 或者,在Win2k之前, GetFileAttributes + FindFirstFile组合)返回的每个文件的isdir来重新确定是否recursion
  3. os.walkos.listdir将执行额外的内存分配 ,string和数组操作等来填充它们的返回值
  4. 然后调用 os.walk返回的每个文件的getsize (它再次调用GetFileAttributesEx

这比Windows资源pipe理器每个文件多3倍的系统调用,加上内存分配和操作开销。

你可以使用Anurag的解决scheme,或者直接调用FindFirstFile / FindNextFile并recursion(这应该与cygwin或其他win32端口 du -s some_directory的性能相当)。

请参阅os.py os.walk的实现, listdir实现listdirwin32_stat (同时由isdirgetsize调用)。

请注意, 在所有平台 (Windows和* nices) ,Python的os.walk并不是最理想的,直到并包括Python3.1。 在Windows和* nices中, os.walk可以在不调用isdir情况下实现遍历,因为FindFirst / FindNext (Windows)和opendir / readdir (* nix)已经通过lpFindFileData->dwFileAttributes (Windows)返回文件types, dirent::d_type (* nix)。

也许违反直觉,对于大多数现代configuration(例如Win7和NTFS,甚至一些SMB实现), GetFileAttributesEx 单个文件的FindFirstFile两倍 (甚至可能比用FindNextFile迭代目录慢)。

更新: Python 3.5包含新的PEP 471 os.scandir()函数,它通过返回文件属性和文件名解决了这个问题。 这个新的function是用来加快内置os.walk() (在Windows和Linux上)。 您可以使用PyPI上的scandir模块来获取旧版Python版本的这种行为,包括2.x.

如果你想要与浏览器相同的速度,为什么不使用Windows脚本来访问相同的function使用pythoncom例如

 import win32com.client as com folderPath = r"D:\Software\Downloads" fso = com.Dispatch("Scripting.FileSystemObject") folder = fso.GetFolder(folderPath) MB = 1024 * 1024.0 print("%.2f MB" % (folder.Size / MB)) 

它将和explorer一样工作,你可以在http://msdn.microsoft.com/en-us/library/bstcxhf7(VS.85).aspx上阅读更多关于Scripting运行时的信息。

我将Python代码的性能与包含190k文件的15k目录树进行了比较,并将其与du(1)命令进行了比较,该命令大概和OS一样快。 Python代码花费了3.3秒,而花费了0.8秒的时间。 这是在Linux上。

我不确定有多less东西要挤出Python代码。 还要注意,du的第一次运行花费了45秒,这明显是在相关的i节点在块caching之前; 因此这个性能在很大程度上取决于系统pipe理其存储的程度。 如果其中之一或两者都不会让我感到惊讶:

  1. os.path.getsize在Windows上是次优的
  2. Windowscaching一次计算的目录内容大小