Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows环境下Python文件夹大小的快速计算_Python_Windows_Size_Directory - Fatal编程技术网

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

Windows环境下Python文件夹大小的快速计算,python,windows,size,directory,Python,Windows,Size,Directory,我正在寻找一种在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

我正在寻找一种在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),在226001个文件和12043个文件夹中完成422GB的存储需要72秒。使用资源管理器属性选项需要40秒

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


Laurent Luce

如果使用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.FindFiles迭代器
win32file.FindFiles
类似,但避免为大型目录创建列表。这有用吗?

这是一个巨大的目录树。正如其他人所说,我不确定你能不能加快速度。。。不是那样的,没有数据的寒冷。这意味着

如果你能以某种方式缓存数据(不确定实际含义是什么),那么你就可以加快速度(我认为…一如既往,度量,度量,度量)

我不认为我必须告诉你如何做缓存,我想,你似乎是一个知识渊博的人。而且我也不知道Windows的即时版本

我突然想到:

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

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

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

微小的调整(如果您坚持使用FindFileW)可能包括确保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或不同的技术。您在一篇评论中提到在后台执行此操作,因此您可以将其构造为使用其中一个用于监视文件夹中更改的包进行增量更新。可能是这个或类似的东西。您可以设置为监视整个树,或者根据该例程的工作方式(我没有使用它),最好在完整树的不同子集上注册多个请求,如果这样可以减少搜索量(当收到通知时),以确定实际更改的内容和现在的大小


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

当文件夹大小超过100G时会发生什么?您是否得到了错误的答案,是否完全失败,是否花费的时间太长,或者是什么?在一台高速机器(2Ghz+-5M内存)上,在226001个文件和12043个文件夹中花费了72秒的时间才超过422GB。我知道我有点贪心,但我希望有一个更好的解决方案。@Laurent,最好编辑你的问题,将这些数据包括在内。这对于帮助人们有效回答问题至关重要。您还可以报告使用Explorer的“属性”对话框和“du”实用程序(例如,从Unxutils)进行比较的时间。在同一个文件夹上
dir/s>NUL
快得多吗?这听起来很像我对如此大量文件的期望。是什么让你觉得可以做得更快?Windows的内置文件大小计数器是否明显更快?您建议的方法需要139秒而不是72秒。我们以前用过这个,速度慢得多。所以,你已经得到了几乎100%的加速,你仍然不满意吗?贪婪的混蛋!;-);-)我建议的方法是否可能运行得较慢,因为它正在遍历所有文件,而您的文件正在跳过列表DIR_EXCLUDES中的系统DIR和文件夹?您可以尝试使用map和reduce来代替for循环。对于数千个文件来说,性能优势可能是巨大的。@jbochi,90%以上的时间消耗在访问文件系统上,因此使用map()之类的工具不太可能有多大的改进。我们将采取的方法是在应用程序的后台计算文件夹大小,以便在用户要求时准备就绪。实际上,Python中的try/except块(与其他一些语言的经验相反)在不引发异常时非常便宜,在任何情况下,代码都是用来捕获无法事先确定的问题(例如某些项目上的“拒绝访问”),因此无法真正避免。在文件系统中执行操作之前,您永远无法检查所有内容。除非文件系统开始支持事务(如SQL),否则某人可以在您检查目录后一纳秒删除它,在您开始使用它之前再删除一纳秒!永远不要跳过文件系统操作的错误/异常处理!它不在这里。事实上,稍微慢一点,考虑到列表是用C代码构建的,并且扫描列表的开销应该比使用迭代器少一些,这也许并不奇怪
# 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))