Windows: Ordnergröße bestimmen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

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!
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

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
querdenker
User
Beiträge: 424
Registriert: Montag 28. Juli 2003, 16:19
Wohnort: /dev/reality

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
Zuletzt geändert von querdenker am Donnerstag 18. Dezember 2008, 08:29, insgesamt 1-mal geändert.
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

@querdenker: genau sowas habe ich gesucht! Danke!
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``?
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

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...?
querdenker
User
Beiträge: 424
Registriert: Montag 28. Juli 2003, 16:19
Wohnort: /dev/reality

@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.
windner
User
Beiträge: 76
Registriert: Freitag 19. Oktober 2007, 11:25

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.
querdenker
User
Beiträge: 424
Registriert: Montag 28. Juli 2003, 16:19
Wohnort: /dev/reality

@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.
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

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/
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?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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 :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

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...;)
windner
User
Beiträge: 76
Registriert: Freitag 19. Oktober 2007, 11:25

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?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

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^^
querdenker
User
Beiträge: 424
Registriert: Montag 28. Juli 2003, 16:19
Wohnort: /dev/reality

@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?
BlackJack

@querdenker: Natürlich ist mein Code nicht immer perfekt, aber ich bemühe mich den dann auch nicht als Lösung anzubieten. :-)
querdenker
User
Beiträge: 424
Registriert: Montag 28. Juli 2003, 16:19
Wohnort: /dev/reality

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.
Antworten