Seite 1 von 1
Paralelisieren von shutil.rmtree
Verfasst: Dienstag 6. November 2007, 09:49
von Amberfox
Hallo Forum,
ich habe ein Python-Script erstellt welches eine große Anzahl an Ordnern mit vielen Dateien als Inhalt löscht.
Zuerst habe ich dies mit shutil.rmtree(folder) probiert, bin dann aber daran hängen geblieben, dass dies doch sehr lange dauert, da ein Ordner nach dem nächsten gelöscht wird.
Ich bin dann hergegangen und habe das Script so beschleunigt:
mydelcmd = "rm -r " + mydelfol
subprocess.Popen(mydelcmd, shell=True)
Nun werden alle Folder parallel (mehr oder weniger) gelöscht. Ich persönlich finde aber die erste Methode mit shutil schöner. Kann man dies auch parallelisieren?? Ein Tip in die richtige Richtung reicht mir schon
Grüße und Danke
Jochen
Verfasst: Dienstag 6. November 2007, 18:31
von veers
Ich weiss ja nicht was für eine Implementierung von rm du verwendest, aber die vom GNU Projekt arbeitet nicht parallel.
Verfasst: Dienstag 6. November 2007, 23:43
von Amberfox
Hallo,
ist vielleicht ein bischen doof ausgedrückt von mir.
Natürlich arbeitet der rm nicht parallel, aber dadurch dass ich das für jeden Ordner absetze und nicht warten muss, bis der Thread zurückkommt, ist das "quasi parallel".
Wenn ich das mit shutil.rmtree mache, wartet mein Script bei jedem Ordner bis der rm-Thread aus dem Kern zurück kommt.
Ich suche nun eine Möglichkeit das zu optimieren
Grüße
Jochen
Verfasst: Dienstag 6. November 2007, 23:47
von CM
Hoi,
verstehe nicht ganz wozu das gut sein soll und so sind dies wirklich nur eine neugierige Fragen und keine besserwisserischen Bemerkungen:
Ist dieses quasiparallele Löschen wirklich schneller? Bei einer Platte gibt es nur einen Lese-/Schreibkopf, nicht wahr? Und bei einem Festplatten-Verbund, sollte das im Zusammenspiel mit Controller und OS doch auch keinen Unterschied machen, oder? Wenn doch, wo kommt der Unterschied her?
Gruß,
Christian
Verfasst: Mittwoch 7. November 2007, 07:37
von Amberfox
Hi,
naja irgendwo hast du Recht. Bei mir ist es gefühlt schon etwas schneller. Da die rm-Threads asynchron in den Kern abgesetzt werden, kann ich die Zeit aber auch nicht mit einem time messen. Ich schau halt ins FS, wie lange es dauert bis alle Ordner weg sind.
Das Script läuft halt schneller durch, da das löschen der Ordner dann im Hintergrund läuft.
Ich lass es erstmal so wie es ist....aber noch eine Frage zum Verständnis,
shutil.rmtree macht doch auch nichts anderes, als das Shell "rm -r" aufzurufen, oder??
Grüße und Danke
Jochen
Verfasst: Mittwoch 7. November 2007, 08:48
von gerold
Amberfox hat geschrieben:shutil.rmtree macht doch auch nichts anderes, als das Shell "rm -r" aufzurufen, oder?
Hallo Jochen!
Nein, das macht es nicht. shutil.rmtree läuft jede Datei und jeden Unterordner rekursiv durch. Prüft jede Datei ob diese ein Ordner ist und übergibt je nach Art der Datei an ``os.remove`` oder ``os.rmdir``. Eine ziemliche Schleifenarbeit. So etwas ist direkt in C garantiert schneller.
Also der Aufwand von "rm" aus "coreutils"
ftp://ftp.gnu.org/gnu/coreutils/ ist schon recht enorm. Du musst dir mindestens "rm.c" und "remove.c" ansehen umd einen Eindruck zu bekommen. Dass "rm" wirklich viel schneller ist, wundert mich nicht. In so einem Fall ist die perfekte Optimierung: per subprocess "rm" aufrufen.
Die Lösung, per subprocess auf so ein spezialisiertes Programm zurück zu greifen ist oft keine schlechte Lösung. Ich verstehe nicht, was dir daran nicht gefällt.
Allerdings würde ich die Argumente als Liste an subprocess übergeben. Dann kümmert sich subprocess um das korrekte Quoting.
mfg
Gerold

Verfasst: Mittwoch 7. November 2007, 10:04
von CM
Hoi,
hab gerade die Quellen durchblättert:
gerold hat geschrieben: Eine ziemliche Schleifenarbeit. So etwas ist direkt in C garantiert schneller.
Ich weiß nicht,ob das einen sichtbaren Unterschied macht. Letztlich wird (bei Linux, aber davon gehe ich bei diesem Post mal aus) auf posix zurückgegriffen und alles weitere ist in C. Vermutung: Es braucht schon sehr viele Ordner (nicht sonstige Dateien), damit man hier einen Unterschied merkt - oder sieht das jemand anders?
Gruß,
Christian
Verfasst: Mittwoch 7. November 2007, 11:40
von Leonidas
gerold hat geschrieben:Die Lösung, per subprocess auf so ein spezialisiertes Programm zurück zu greifen ist oft keine schlechte Lösung. Ich verstehe nicht, was dir daran nicht gefällt.
Windows hat kein `rm`. Damit bringst du also platformabhängigkeit rein, wo es eigentlich keine bräuchte. Dann musst du testen ob es Windows ist und dort dann `del` aufrufen und somit für jede Platform gucken wie das Löschkommando dort ist.
Verfasst: Mittwoch 7. November 2007, 11:56
von gerold
Leonidas hat geschrieben:Windows hat kein `rm`. Damit bringst du also platformabhängigkeit rein, wo es eigentlich keine bräuchte. Dann musst du testen ob es Windows ist und dort dann `del` aufrufen und somit für jede Platform gucken wie das Löschkommando dort ist.
Hallo Leonidas!
Ist das ein Problem?
Code: Alles auswählen
>>> import sys
>>> if sys.platform.startswith("win"):
... print "Windows"
... else:
... print "Linux und Co"
...
Windows
>>>
(man könnte je nach Bedarf und Einsatzzweck noch weitere Plattformen in die Auswahl mit einbeziehen)
So etwas würde man natürlich nicht oder nur gut getestet für ein Python-Erweiterungsmodul verwenden. Aber sicher doch um schnell und einfach ein spezielles Problem zu lösen. Die ganze Linux-/Unix-Shellprogrammierung baut darauf auf, kleine Dienstprogramme gezielt einzusetzen. Und das funktioniert immer noch sehr gut.
lg
Gerold

Verfasst: Mittwoch 7. November 2007, 12:12
von Leonidas
gerold hat geschrieben:Ist das ein Problem?
Code: Alles auswählen
>>> import sys
>>> if sys.platform.startswith("win"):
... print "Windows"
... else:
... print "Linux und Co"
...
Windows
>>>
(man könnte je nach Bedarf und Einsatzzweck noch weitere Plattformen in die Auswahl mit einbeziehen)
Klar, das geht schon. Aber weißt du wie der Befehl fürs Löschen unter Plan 9, Inferno, und $IRGENDEIN_EXOTISCHES_OS_AUF_DEM_PYTHON_LÄUFT ist? Du kannst ja für die bekannten Platformen so etwas anbieten, aber generell würde ich das als "Unschön" bezeichnen. Du nutzt ja sicher auch Pythons Stdlib, obwohl man unter Windows einige Sachen auch über `ctypes` und die MSVCRT lösen kann.
Der Code ist optimalerweise für alle Plattformen gleich. Das `shutil.rmtree` nicht sonderlich schnell ist mag ja sein, aber da wäre es besser dem Interpreter eine Implementation zu geben, die besser ist. Davon profitieren alle. Klar, das klingt nun etwas arg "abgehoben" und die Lösung Subprozesse zu starten um Dinge zu erledigen geht ja auch, aber meines Ermessens ist sie einfach nicht schön.
gerold hat geschrieben:Aber sicher doch um schnell und einfach ein spezielles Problem zu lösen. Die ganze Linux-/Unix-Shellprogrammierung baut darauf auf, kleine Dienstprogramme gezielt einzusetzen. Und das funktioniert immer noch sehr gut.
Das dachten sich auch die Entwickler von Git. Das ist schnell und eine Mischung aus C, Perl und bash die unter Windows nicht richtig lauffähig ist. Daran ist nicht nur der C-Teil schuld.
Verfasst: Mittwoch 7. November 2007, 12:15
von BlackJack
Das wäre ein Problem falls es sich wirklich nur um "gefühlte" Geschwindigkeit handelt. Also ich würde messen wieviel es bringt bevor ich mir eine eventuell unnötige Platformabhängigkeit einbaue.
Verfasst: Mittwoch 7. November 2007, 19:17
von Amberfox
Hallo,
vielen Dank für die Denkanstöße!!
Also ich denke ich lasse es dann erstmal so. Die angesprochenen rm.c und remove.c schaue ich mit interesse halber einfach mal an.
Die Platformunabhängigkeit ist in meinem Fall erstmal nicht ganz so wichtig, daher nutze ich das Aufrufen des "rm", um einfach die gefühlte Geschwindigkeit zu haben. Ich schau mal ob ichs doch schaffe die Zeit zu stoppen und melde mich dann, wenn ich wirklich Testergebnisse habe, was schneller geht.
Viele Grüße in die Runde
Jochen