簡體   English   中英

Windows上的Python快速文件夾大小計算

[英]fast folder size calculation in Python on Windows

我正在尋找一種快速計算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內存)上,在226,001個文件和12,043個文件夾中花了72秒超過422GB。 使用資源管理器屬性選項需要40秒。

我知道我有點貪心,但我希望有更好的解決方案。

勞倫特盧斯

快速分析代碼表明,僅在FindFilesW()調用中就消耗了90%以上的時間。 這意味着通過調整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打開屬性窗口。 在完成這一次(使用你的代碼)並獲得40秒后,我現在從這兩種方法中消耗了20秒。 換句話說, 你的代碼實際上和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.FindFilesIterator “類似於win32file.FindFiles ,但是避免為巨大的目錄創建列表”。 這有幫助嗎?

這是一個目錄樹的巨大。 正如其他人所說,我不確定你是否可以加快速度......不像那樣,冷酷無數據。 這意味着...

如果您可以以某種方式緩存數據(不確定實際含義是什么),那么您可以加快速度(我認為......一如既往地衡量,衡量,衡量)。

我不認為我必須告訴你如何進行緩存,我想,你似乎是一個知識淵博的人。 而且無論如何我都不會知道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))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM