Seite 1 von 1

Windows: Ordnergröße bestimmen

Verfasst: Mittwoch 17. Dezember 2008, 08:49
von nemomuk
Hallo,

ich suche momentan nach einer schnellen Lösung, die Größe eines Ordners zu ermitteln. Natürlich könnte man mit os.walk alles kompliziert aufsummieren - das dauert aber und ist etwas umständlich... Gibt es eine andere Lösung?

Danke!

Verfasst: Mittwoch 17. Dezember 2008, 09:35
von rayo
Hi

Eine andere Loesung als von jeder Datei die Groesse auszusummieren kenne ich nicht. Das ganze ist aber nicht wirklich schwierig und aufwaendig:

Code: Alles auswählen

def iter_files(path):
    for root, dirs, filenames in os.walk(path):
        for filename in filenames:
            yield os.path.join(root, filename)

def dir_size(directory):
    return sum(os.path.getsize(x) for x in iter_files(directory))
Gruss

Verfasst: Mittwoch 17. Dezember 2008, 12:51
von querdenker
Unter Windows kann man so machen

Code: Alles auswählen

import win32com.client

def get_dirsize(dir2check):
    fso=win32com.client.Dispatch("Scripting.FileSystemObject")
    folder=fso.GetFolder(dir2check)
    total=folder.Size
    return total


print get_dirsize(path2query) #logischerweise mit einem gültigen Pfad aufrufen!
Ist 'nur' eine Kopie aus einem Modul, das ich mal geschrieben habe.


mfg, querdenker

EDIT : Code-Cleanup

Verfasst: Mittwoch 17. Dezember 2008, 13:00
von nemomuk
@querdenker: genau sowas habe ich gesucht! Danke!

Verfasst: Mittwoch 17. Dezember 2008, 13:15
von BlackJack
@querdenker: Könntest Du mal kurz erklären, was Die Rechnung da soll? Laut MSDN ist `Size` die Grösse in Bytes, was veranstaltest Du da für komische Sachen mit!?

Und warum ``&`` statt ``and``?

Verfasst: Mittwoch 17. Dezember 2008, 13:27
von nemomuk
Nun stehe ich leider vor einem Problem:

Code: Alles auswählen

def get_folder_size(self, path):
    try:
        fso = win32com.client.Dispatch('Scripting.FileSystemObject')
        size = fso.GetFolder(path).Size
    except Exception, e:
        print e
        size = 0
    return size

path = path.decode('iso-8859-2')
size = self.get_folder_size(path)
Fehlermeldung:

Code: Alles auswählen

(-2147221008, 'CoInitialize wurde nicht aufgerufen.', None, None)
Das ganze läuft in ein und demselben Thread. Habe leider nichts passendes zu diesem Fehler gefunden.

Jemand ein Ahnung was das sein könnte...?

Verfasst: Mittwoch 17. Dezember 2008, 13:37
von querdenker
@BlackJack
Ich brauche für die Rechnungslegung MB, daher das "rumrechnen".

Warum '&' statt 'and'? Frag mich bitte nicht. Ich habe das Script damals zwischen dem Umzug einer Serverfarm und einem Servercrash (14 Datenbanken betroffen, die Kunden sollten am nächsten Tag wieder arbeiten) in einer Nacht- und Nebelaktion geschrieben. Die Zahlen waren damals plausibel, deswegen habe ich das so als i.O befunden.

Verfasst: Mittwoch 17. Dezember 2008, 13:43
von windner
Ich glaube, daß das FileSystemObject auch nichts anderes macht, als
die einzelnen Größen zusammenzählen.
Es gibt nämlich irgendwo in der Registry einen Schlüssel, mit dem
man den Explorer anweisen kann, die Größen von Ordnern anzuzeigen.
Und der braucht genauso lang wie dein oben gezeigter Entwurf.

Verfasst: Mittwoch 17. Dezember 2008, 13:43
von querdenker
@SchneiderWeisse: Schau dir mal deinen Pfad an.

Code: Alles auswählen

>>> import win32com
>>> import win32com.client
>>> total=0.0
>>> fso=win32com.client.Dispatch("Scripting.FileSystemObject")
>>> folder=fso.GetFolder('c:/devel')
>>> total=folder.Size
>>> print total
161771596
>>> total2=0.0
>>> total2=fso.GetFolder('c:/devel').Size
>>> total2
161771596
>>>
Mal gerade in der Shell durchgehackt, geht.

Verfasst: Mittwoch 17. Dezember 2008, 13:48
von nemomuk
sehr komisch, wenn ich die "Pfade" ausgebe per print und danach manuell in der IDLE eingebe funktioniert es, im Skript nicht...

http://paste.pocoo.org/show/95731/

Verfasst: Mittwoch 17. Dezember 2008, 14:10
von BlackJack
@querdenker: Und was soll das `round()`? Solange Du kein ``from __future__ import division`` ganz oben stehen hast, kommt bei der Rechnung immer eine ganze Zahl heraus, aus der Du dann per `round()` erst eine Fliesskommazahl machst, um diese dann sofort wieder in eine ganze Zahl umzuwandeln. Also zwei Umwandlungen die im Endeffekt *nichts* bewirken.

Und warum bindest Du Namen an ein Objekt, die Du kurz darauf an etwas anderes bindest!? ``total = 0.0`` ist total sinnfrei.

Wann sollte `final` bei der ``if``-Anfrage jemals kleiner als 0 werden? Und warum vergleichst Du die ganze Zahl `total` mit einer Fliesskomma-Null?

Verfasst: Mittwoch 17. Dezember 2008, 14:13
von Leonidas
windner hat geschrieben:Ich glaube, daß das FileSystemObject auch nichts anderes macht, als
die einzelnen Größen zusammenzählen.
Ja, das nehme ich auch stark an. Somit hat man aus einem platformunabhängigen Code einen Windows-only-Code gemacht der keinen Nutzen hat und zusätzlich noch pywin32 vorraussetzt. Das könnte man direkt Anti-Optimierung nennen :)

Verfasst: Mittwoch 17. Dezember 2008, 14:53
von nemomuk
naja, erstens: Mein Programm ist nur für Windows ausgelegt und zweitens ist die Methode mit win32com um ein vielfaches schneller.

Trotzdem wäre es ganz hilfreich, wenn jemand etwas mit ->meinem<- Problem anfangen könnte...;)

Verfasst: Mittwoch 17. Dezember 2008, 15:05
von windner
Leonidas hat geschrieben:Das könnte man direkt Anti-Optimierung nennen.
:twisted:
Wollte auch sowas sagen, habe mich aber nicht getraut.
zweitens ist die Methode mit win32com um ein vielfaches schneller.
Ehrlich?

Verfasst: Mittwoch 17. Dezember 2008, 15:09
von Leonidas
SchneiderWeisse hat geschrieben:zweitens ist die Methode mit win32com um ein vielfaches schneller.
Ich fordere zwei minimale Programme die beide Methoden benutzen zu Benchmarken, mit einsprechend großen Ordnern und entsprechend vielen Durchläufen. Weder NFTS noch FAT halten die Ordnergröße AFAIR irgendwo vor, also kann ich es schwer glauben dass da besonders große Unterschiede auftreten werden.

Verfasst: Mittwoch 17. Dezember 2008, 15:21
von nemomuk

Code: Alles auswählen

0.515999794006 win32
4.5150001049 pure-python
0.484999895096 win32
4.48400020599 pure-python
0.484999895096 win32
4.46799993515 pure-python
0.485000133514 win32
4.40599989891 pure-python
0.483999967575 win32
4.43799996376 pure-python

Code: Alles auswählen

import time
import win32com.client
import os

def main():
    for i in range(5):
        path = 'C:\\Programme'
        
        start = time.time()
        fso = win32com.client.Dispatch('Scripting.FileSystemObject')
        size = fso.GetFolder(path).Size
        print time.time()-start, 'win32'
        
        start = time.time()
        size = 0
        for root, dirs, filenames in os.walk(path):
            for filename in filenames:
                 size += os.path.getsize(os.path.join(root, filename))
        print time.time()-start, 'pure-python'
    
if __name__ == '__main__':
    main()
Der Unterschied ist wohl nicht zu übersehen...;)
Ich warte immer noch auf die Lösung des Problems^^

Verfasst: Donnerstag 18. Dezember 2008, 00:28
von querdenker
@BlackJack: Der Code ist von anno Tuck, und wie schon erwähnt, unter hohem Streß (180 Arbeitstunden in 2 Wochen vergißt man nicht) entstanden. Das einzige was mich damals interessiert hat waren Zahlen, die ich der Buchhaltung in die Hand drücken konnte ohne stundenlang irgendwelche Verzeichnisgrößen zusammenzurechnen. Ich meine mich auch erinnern zu können das ich was von "sollte ich bei Gelegenheit mal überarbeiten" geschrieben habe. Ist dein Code von vor [Zeitraum] perfekt?

Verfasst: Donnerstag 18. Dezember 2008, 00:44
von BlackJack
@querdenker: Natürlich ist mein Code nicht immer perfekt, aber ich bemühe mich den dann auch nicht als Lösung anzubieten. :-)

Verfasst: Donnerstag 18. Dezember 2008, 00:49
von querdenker
Ok, Punkt für dich. Ich hätte vielleicht einfach ein dickes "WARNUNG: SCHLECHTER CODE" über das Posting kleben sollen. :D

Gerade noch mal gebuddelt: Die Berechungsgeschichte kommt aus einer noch älteren Sache. Ich muß das Ding wirklich mal überarbeiten.

EDIT: habe mal in meinem Beispiel den 'Müll' entfernt.