Windows环境下Python中文件夹大小的快速计算

2024-04-24 01:30:27 发布

您现在位置: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

当文件夹大小超过100克时,这还不够好。有什么改进的办法吗?

在一台高速机器(2Ghz+-5G内存)上,226001个文件和12043个文件夹中的422GB需要72秒。使用资源管理器属性选项需要40秒。

我知道我有点贪心,但我希望有更好的解决办法。

洛朗·卢斯


Tags: pathnamein文件夹sizegetreturnif
3条回答

如果使用os.walk,则不需要使用递归算法。Please check this question

你应该计时两种方法,但这应该快得多:

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类似,但避免为大型目录创建列表。有帮助吗?

对代码的快速分析表明,超过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或者类似的东西。您可以设置为监视整个树,或者根据该例程的工作方式(我没有使用它),您最好在整个树的不同子集上注册多个请求,如果这样可以减少您必须执行的搜索量(在收到通知时),以确定实际更改的内容和现在的大小。

编辑:我在评论中询问您是否考虑到了WindowsXP和更高版本所做的繁重的文件系统元数据缓存。我刚刚对照Windows本身检查了您的代码(和我的代码)的性能,选择了C:\文件夹中的所有项,并按Alt-Enter键打开属性窗口。在这一次(使用您的代码)并获得40秒的运行时间之后,我现在从两个方法获得20秒的运行时间。换句话说,至少在我的机器上,您的代码实际上与Windows本身一样快。

相关问题 更多 >