在Windows上使用Python进行快速文件夹大小计算

我正在寻找一种快速的方法来计算在Windows上的Python文件夹大小。 这是我迄今为止:

def get_dir_size(path): total_size = 0 if platform.system() == 'Windows': try: items = win32file.FindFilesW(path + '\\*') except Exception, err: return 0 # Add the size or perform recursion on folders. for item in items: attr = item[0] name = item[-2] size = item[5] if (attr & win32con.FILE_ATTRIBUTE_DIRECTORY) and \ not (attr & win32con.FILE_ATTRIBUTE_SYSTEM): # skip system dirs if name not in DIR_EXCLUDES: total_size += get_dir_size("%s\\%s" % (path, name)) total_size += size return total_size 

当文件夹的大小超过100G时,这不够好。 任何想法如何改善?

在一台速度很快的机器上(2Ghz + – 5G的RAM),在226,001个文件和12,043个文件夹中花费了72秒时间。 使用资源pipe理器属性选项需要40秒。

我知道我有点贪婪,但我希望有一个更好的解决scheme。

Laurent Luce

对代码进行快速分析表明,超过90%的时间仅在FindFilesW()调用中消耗。 这意味着通过调整Python代码的任何改进都是微不足道的。

微小的调整(如果你坚持使用FindFilesW)可以包括确保DIR_EXCLUDES是一个集合,而不是一个列表,避免在其他模块上重复查找,并懒洋洋地索引到item [],以及移动外部的sys.platform检查。 这包括这些变化和其他, 但不会超过1-2%的加速

 DIR_EXCLUDES = set(['.', '..']) MASK = win32con.FILE_ATTRIBUTE_DIRECTORY | win32con.FILE_ATTRIBUTE_SYSTEM REQUIRED = win32con.FILE_ATTRIBUTE_DIRECTORY FindFilesW = win32file.FindFilesW def get_dir_size(path): total_size = 0 try: items = FindFilesW(path + r'\*') except pywintypes.error, ex: return total_size for item in items: total_size += item[5] if (item[0] & MASK == REQUIRED): name = item[8] if name not in DIR_EXCLUDES: total_size += get_dir_size(path + '\\' + name) return total_size 

唯一显着的加速将来自于使用不同的API或不同的技术。 您在后面提到的评论中提到过,所以您可以使用其中一个包来监视文件夹中的更改来构建增量更新。 可能是FindFirstChangeNotification API或类似的东西。 你可以设置监视整个树,或者根据这个例程的工作方式(我没有使用它),如果在整个树的不同子集上注册多个请求可能会更好,如果这减少了搜索的数量(通知时)来确定实际上发生了什么变化以及现在的规模。

编辑:我在评论中问你是否考虑到Windows XP及其后续的大量文件系统元数据缓存。 我只是检查你的代码(和我的)对Windows本身的性能,选择我的C:\文件夹中的所有项目,并按下Alt-Enter来调出属性窗口。 这样做一次(使用你的代码),并获得了40s的时间,现在我从这两种方法已经过了20s。 换句话说, 您的代码实际上与Windows本身一样快 ,至少在我的机器上。

如果使用os.walk,则不需要使用递归算法。 请检查这个问题 。

你们应该两种方法,但这应该是更快:

 import os def get_dir_size(root): size = 0 for path, dirs, files in os.walk(root): for f in files: size += os.path.getsize( os.path.join( path, f ) ) return size 

我目前没有Windows的测试框,但是文档指出win32file.FindFilesIteratorwin32file.FindFiles类似,但是避免为巨大的目录创建列表。 这有帮助吗?

这是一个目录树的伟大的。 正如其他人所说,我不知道你可以加快速度…不是那样,冷W / O数据。 这意味着…

如果你可以缓存数据,不知怎的(不知道实际的含义是什么),那么你可以加快速度(我认为…一如既往,测量,测量,衡量)。

我想我不必告诉你如何做缓存,我想,你看起来像一个有知识的人。 而且我也不知道Windows的袖口。 😉

这跳到我身上:

 try: items = win32file.FindFilesW(path + '\\*') except Exception, err: return 0 

异常处理可以为您的算法增加大量的时间。 如果您可以以不同的方式指定路径,则您可以以一种您始终知道安全的方式,从而防止需要捕获异常(例如,在查找文件夹中的文件之前首先检查给定的路径是否为文件夹),则可以发现一个显着的加速。

 # Size of File Folder/Directory in MBytes import os # pick a folder you have ... folder = 'D:\\zz1' folder_size = 0 for (path, dirs, files) in os.walk(folder): for file in files: filename = os.path.join(path, file) folder_size += os.path.getsize(filename) print "Folder = %0.1f MB" % (folder_size/(1024*1024.0))