Je veux trouver rapidement la taille totale de n'importe quel dossier en utilisant 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)
C'est le script simple que j'ai écrit pour obtenir la taille totale du dossier, cela a pris environ 60 secondes (+ -5 secondes). En utilisant le multitraitement, je l'ai réduit à 23 secondes sur une machine quadricœur.
En utilisant l'explorateur de fichiers Windows, cela ne prend que ~ 3 secondes (clic droit -> propriétés pour voir par vous-même). Existe-t-il un moyen plus rapide de trouver la taille totale d'un dossier proche de la vitesse à laquelle Windows peut le faire?
Windows 7, python 2.6 (A fait des recherches mais la plupart du temps les gens utilisaient une méthode très similaire à la mienne) Merci d'avance.
Vous êtes désavantagé.
L'Explorateur Windows utilise presque certainement FindFirstFile
/ FindNextFile
pour parcourir la structure du répertoire et collecter la taille (via lpFindFileData
) en un seul passage, ce qui constitue essentiellement un seul appel système par fichier.
Python n'est malheureusement pas votre ami dans ce cas. Donc,
os.walk
premiers appels os.listdir
(qui appelle en interne FindFirstFile
/FindNextFile
) os.walk
appelle ensuite isdir
pour chaque fichier renvoyé par os.listdir
(Qui appelle en interne GetFileAttributesEx
- ou, avant Win2k, un combo GetFileAttributes
+ FindFirstFile
) pour déterminer à nouveau s'il faut récursif ou nonos.walk
Et os.listdir
Effectueront une allocation de mémoire supplémentaire , des opérations sur les chaînes et les tableaux, etc. pour remplir leur valeur de retourgetsize
pour chaque fichier renvoyé par os.walk
(qui appelle à nouveau - GetFileAttributesEx
)Cela représente 3 fois plus d'appels système par fichier que l'Explorateur Windows, plus l'allocation de mémoire et la surcharge de manipulation.
Vous pouvez soit utiliser la solution d'Anurag, soit essayer d'appeler FindFirstFile
/FindNextFile
directement et récursivement (ce qui devrait être comparable aux performances d'un cygwin
ou autre port win32du -s some_directory
.)
Reportez-vous à os.py
pour l'implémentation de os.walk
, posixmodule.c
pour l'implémentation de listdir
et win32_stat
(Invoqué à la fois par isdir
et getsize
.)
Notez que Python os.walk
Est sous-optimal sur toutes les plateformes (Windows et * nices), jusqu'à Python3.1 inclus. Sous Windows et * nices, os.walk
Pouvait réaliser la traversée en une seule passe sans appeler isdir
puisque FindFirst
/FindNext
(Windows) et opendir
/readdir
(* nix) renvoie déjà le type de fichier via lpFindFileData->dwFileAttributes
(Windows) et dirent::d_type
(* nix).
Peut-être contre-intuitivement, sur la plupart des configurations modernes (par exemple Win7 et NTFS, et même certaines SMB) GetFileAttributesEx
est deux fois aussi lent comme FindFirstFile
d'un seul fichier (peut-être même plus lent que l'itération sur un répertoire avec FindNextFile
.)
Mise à jour: Python 3.5 inclut le nouveau PEP 471os.scandir()
fonction qui résout ce problème en renvoyant des attributs de fichier avec le nom de fichier. Cette nouvelle fonction est utilisée pour accélérer le os.walk()
intégré (sous Windows et Linux). Vous pouvez utiliser le module scandir sur PyPI pour obtenir ce comportement pour les anciennes versions Python, y compris 2.x.
Si vous voulez la même vitesse qu'Explorer, pourquoi ne pas utiliser les scripts Windows pour accéder aux mêmes fonctionnalités en utilisant pythoncom, par exemple.
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))
Il fonctionnera de la même manière que l'Explorateur, vous pouvez en savoir plus sur l'exécution du script sur http://msdn.Microsoft.com/en-us/library/bstcxhf7 (VS.85) .aspx .
J'ai comparé les performances du code Python à une arborescence de répertoires de 15k contenant 190k fichiers et je l'ai comparée à la commande du(1)
qui va probablement aussi vite que le système d'exploitation. Le = Python a pris 3,3 secondes par rapport à du qui a pris 0,8 secondes. C'était sous Linux.
Je ne suis pas sûr qu'il y ait beaucoup à tirer du code Python. Notez également que la première exécution de du a pris 45 secondes, ce qui était évidemment avant que les nœuds i pertinents ne se trouvent dans le cache de bloc ; par conséquent, ces performances dépendent fortement de la façon dont le système gère son magasin. Cela ne me surprendrait pas si l'un ou les deux: