Seite 1 von 2
Löschen eines Verzeichnisses erzwingen
Verfasst: Dienstag 11. September 2012, 21:36
von BastiL
Hallo zusammen,
ich möchte unter Linux in Python 2.7 ein (nicht-leeres) Verzeichnis löschen. Während ein
auf der Konsole klaglos funktioniert, geht das mit
nicht immer, nachmal bekomme ich:
rm: Entfernen von „Verzeichnis“ nicht möglich: Das Verzeichnis ist nicht leer
Auch shutil.rmtree versagt manchmal. Leider habe ich noch nicht herausgefunden, wann welches Kommando Probleme hat. Gibt es keine einfache Alternative die immer geht?
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Dienstag 11. September 2012, 22:42
von BlackJack
@BastiL: Es sollte eigentlich keinen Unterschied machen ob man unter den selben Vorbedingungen das ``rm`` auf einer Konsole absetzt oder über `os.system()`. Das heisst irgend etwas muss in beiden Fällen anders sein. Andere Datei- oder Benutzerrechte, andere Dateisysteme, oder irgend welche anderen Randbedingungen die nicht übereinstimmen.
Sind noch Dateien geöffnet oder werden dort parallel zum Löschen angelegt? Hast Du die Rechte alles zu löschen was sich dort befindet?
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Dienstag 11. September 2012, 22:45
von deets
Abgesehen davon, dass du besser subprocess.call verwenden solltest, kann dein Problem so nicht existieren. Denn der Shell-Aufruf macht exakt das, was dein os.system-Aufruf auch tut. Dementsprechend gibt es auch nichts "besseres".
Da du keine konkrete Fehlermeldung angibst, kann man nur raten. Es koennte zB sein, dass dein Python-Programm etwas in dem Verzeichnis tut wie zB eine Datei anlegen und geoeffnet halten, die dann das rm-Kommando nicht entfernen kann. Das faellt dir in der Shell natuerlich nicht auf, weil dein Programm dann gerade nicht laeuft.
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 06:39
von BastiL
Hallo,
das Verzeichnis habe ich zuvor für temporäre Dateien angelegt. Rechte habe ich folglich. Die temporären Dateien werden gelöscht, das Verzeichnis selbst bleibt stehen. Fehlermeldung wie oben genannt: rm: Entfernen von „Verzeichnis“ nicht möglich: Das Verzeichnis ist nicht leer
Ich habe ein Beispiel abgezogen. Hier ein ls -la, das Verzeichnis 17613202, das ich zuvor unter Python angelegt habe:
Code: Alles auswählen
ls -lat | grep 17613202
drwxrwxrwx 1 root root 48 12. Sep 07:31 17613202
ls -lat 17613202
insgesamt 8
drwxrwxrwx 1 root root 48 12. Sep 07:31 .
drwxrwxrwx 1 root root 8192 12. Sep 07:31 ..
Eigentümer ist interessanterweise root, obwohl ich Python nicht unter root laufen habe.
wenn ich jetzt folgendes unter Python als User absetze:
dann löscht er den Ordner wie ich gerade feststelle.
Aus meinem Programm heraus rufe ich dasselbe Kommando auf und er löscht das Verzeichnis nicht. Ich denke Eure Vermutung das PYthon noch etwas im Vezeichnis macht stimmt. Wie kann ich das weiter eingrenzen? Ich werde heute abend versuchen hier ein Beispielprogramm zu posten.
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 07:52
von Sr4l
Benutzt du relative Pfade und bist vll einfach in einem Arbeitsverzeichnis als in der Konsole?
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 14:18
von BastiL
Das Verzeichnis stimmt, das sieht man an der Fehlermeldung die ich bekomme:
rm: Entfernen von „Verzeichnis“ nicht möglich: Das Verzeichnis ist nicht leer
Das zeigt, dass das Verzeichnis "Verzeichnis" da ist. Es sollte aber eigentlich:
1. Leer sein und
2. sollte es rm -rf egal sein, ob das Verzeichnis leer ist oder nicht.
Ich versuche heute abend, ein Beispielprogramm hier zu posten.
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 15:33
von BlackJack
@BastiL: 2. Stimmt nicht so ganz. Es ist nur egal wenn darin alles gelöscht werden konnte. Wenn es dort Dateien gibt, die nicht gelöscht wurden, entweder weil die Rechte nicht ausreichen oder weil sie dort angelegt wurden nachdem die Dateien in einem Unterverzeichnis gelöscht wurden, dann kann auch ``rm -rf`` keine nicht-leeren Unterverzeichnisse entfernen, ganz einfach weil das der Systemaufruf den ``rm`` verwendet nun mal nicht hergibt. Wäre auch schlecht wenn das einfach so ginge.
Das ``-f`` bedeutet auch nicht das jegliches Löschen erzwungen werden kann, sondern dass bei Fehlern oder Problemen bei den Teilaufgaben des Löschens einfach ohne nachzufragen weiter gemacht wird.
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 19:25
von BastiL
Ok, das Problem scheint zu sein, dass ich vor dem Löschversuch über alle Dateien im Ordner mit os.listdir loope. Anschließend löscht rm -rf zwar alle Dateien im Verzeichnis aber nicht das Verzeichnis selbst. Wenn ich das loopen weglasse läuft alles. Muss ich irgendwie die Instanz von os.listdir schließen?
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 19:49
von lunar
@BastiL Quelltext bitte…
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 20:16
von BlackJack
@BastiL: `os.listdir()` liefert eine Liste — was willst Du da „schliessen”?
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 20:53
von BastiL
Hier der Schnipsel, ist noch recht länglich....
Code: Alles auswählen
#! /bin/python
import os, urllib, csv, datetime
def run():
id=11050544
daten = []
os.mkdir(str(id))
i=0
while True:
conn = urllib.urlopen("http://www.comdirect.de/"\
+ "inf/kursdaten/historic.csv?DATETIME_TZ_START_RANGE_FORMATED=01.01.2012" +\
"&ID_NOTATION=" + str(id) + "&INTERVALL=16" + \
"&OFFSET=" + str(i) + "&DATETIME_TZ_END_RANGE_FORMATED=01.08.2012 &WITH_EARNINGS=true")
if conn.getcode() != 200:
break
urllib.urlretrieve("http://www.comdirect.de/inf/kursdaten/" + \
"historic.csv?DATETIME_TZ_START_RANGE_FORMATED=01.01.2012" +\
"&ID_NOTATION=" + str(id) + "&INTERVALL=16" + \
"&OFFSET=" + str(i) + "&DATETIME_TZ_END_RANGE_FORMATED=01.08.2012" + \
"&WITH_EARNINGS=true", str(id) + "/offset%04i.csv" %i)
i=i+1
# Daten zusammenlesen und in Liste speichern
for file in sorted(os.listdir(str(id))):
reader = csv.reader(open(str(id) + "/" + file, "r"), delimiter=";")
for row in reader:
if len(row) > 1 and row[0] != "Datum":
datum = datetime.date(int(row[0].split(".")[2]),\
int(row[0].split(".")[1]), int(row[0].split(".")[0]))
zeit = datetime.time(int(row[1].split(":")[0]),\
int(row[1].split(":")[1]))
daten.append([datum.strftime("%d.%m.%Y"), \
zeit.strftime("%H:%M"), \
float(row[2].replace(".","").replace(",",".")), \
float(row[3].replace(".","").replace(",",".")), \
float(row[4].replace(".","").replace(",",".")), \
float(row[5].replace(".","").replace(",",".")), \
float(row[6].replace(".","").replace(",","."))])
os.system('rm -rf ' + str(id))
def main():
run()
if __name__ == "__main__":
main()
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 21:04
von EyDu
Du könnstest einfach die geöffneten Dateien auch wieder schließen. Das with-Statement eignet sich übrigens wunderbar dafür, dann kann man nichts mehr vergessen.
Deine Code hat aber noch einige andere Schwachstellen:
- Das Zusammenbasteln der Strings ist mehr als grausam. String Formatting existiert, damit kann man die Strings auch noch lesen.
- Die meisten Strings sollte man wahrscheinlich mit einer entsprechenden Bibliothek zusammensetzen, so schleichen sich da doch nur Fehler ein
- file ist ein schlechter Name (zumal es auch noch ein Dateiname ist), da er einen Standardbezeichner verdeckt
- Dateipfade sollte man mit os.path.join zusammensetzen und nicht mittels +
- Bei dir ist unglaublich viel doppelt oder unterscheidet sich nur an einer Stelle, das kann man alles zusammenfassen
- Die ganzen replace-Statements sehen mehr als abenteuerlich aus.
- Und bitte setze deinen Code doch in PYTHON-Codetags und nicht einfach nur in Codetags.
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 21:21
von Hyperion
EyDu hat geschrieben:
- Und bitte setze deinen Code doch in PYTHON-Codetags und nicht einfach nur in Codetags.
Hab ich noch einmal übernommen

Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 21:24
von BlackJack
@BastiL: Ergänzend: Das Leerzeichen in der ersten Zeile nach ``#!`` gehört da nicht hin. Ausserdem ist ``#!/usr/bin/env python`` an der Stelle üblicher, weil dann der Python-Interpreter nur irgend wo im Suchpfad $PATH liegen muss und nicht zwingend unter ``/bin/python``. Bei mir, und damit wohl mindestens bei allen Debian- und Ubuntu-Nutzern, wäre ``/bin/python`` zum Beispiel falsch.
Die '\' an den Zeilenenden dürften fast alle überflüssig sein. Solange noch mindestens eine Klammer offen ist, weiss Python dass die „logische” Zeile noch nicht zu ende sein kann.
Die Programmlogik kommt mir komisch vor. Für jede Datei die herunter geladen wird, werden jedes mal alle Dateien aus dem temporären Verzeichnis in den Speicher eingelesen‽
Sind die temporären Dateien überhaupt notwendig?
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 21:32
von BastiL
BlackJack hat geschrieben:
Die Programmlogik kommt mir komisch vor. Für jede Datei die herunter geladen wird, werden jedes mal alle Dateien aus dem temporären Verzeichnis in den Speicher eingelesen‽
Sind die temporären Dateien überhaupt notwendig?
Ja du hast recht sorry, da habe ich beim kopieren eine Einrückung zu viel eingebaut.
Ich brauche zumindest eine temporäre Datei, die ich dann aber im Prinzip direkt einlesen könnte ....
Danke für die Hinweise
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 21:40
von BastiL
Danke für die umfangreichen Tipps. Da habe ich gleich Fragen dazu ...
EyDu hat geschrieben:Du könnstest einfach die geöffneten Dateien auch wieder schließen. Das with-Statement eignet sich übrigens wunderbar dafür, dann kann man nichts mehr vergessen.
Macht Sinn, manchmal sieht man den Wald nicht mehr. Das with-statement kenne ich aber nicht
EyDu hat geschrieben:
Deine Code hat aber noch einige andere Schwachstellen:
- Das Zusammenbasteln der Strings ist mehr als grausam. String Formatting existiert, damit kann man die Strings auch noch lesen.
- Die meisten Strings sollte man wahrscheinlich mit einer entsprechenden Bibliothek zusammensetzen, so schleichen sich da doch nur Fehler ein
Welche Bibliothek kannst Du dafür empfehlen?
EyDu hat geschrieben:
- Dateipfade sollte man mit os.path.join zusammensetzen und nicht mittels +
Warum denn?
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 21:44
von BlackJack
@BastiL: Wozu brauchst Du die temporäre Datei?
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Mittwoch 12. September 2012, 21:45
von Hyperion
BastiL hat geschrieben:
Macht Sinn, manchmal sieht man den Wald nicht mehr. Das with-statement kenne ich aber nicht
Ist ganz einfach:
Code: Alles auswählen
with open(...) as handler:
# handler ist hier file-Objekt
BastiL hat geschrieben:
EyDu hat geschrieben:
- Dateipfade sollte man mit os.path.join zusammensetzen und nicht mittels +
Warum denn?
Darum 
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Donnerstag 13. September 2012, 06:29
von BastiL
BlackJack hat geschrieben:@BastiL: Wozu brauchst Du die temporäre Datei?
Warscheinlich weil ich nicht weiss, wie ich eine csv-Datei direkt ohne Download parsen kann...
Re: Löschen eines Verzeichnisses erzwingen
Verfasst: Donnerstag 13. September 2012, 06:41
von BlackJack
@BastiL: `urllib.urlopen()` gibt ein Objekt mit einer `read()`-Methode zurück und `csv.reader()` möchte gerne ein Objekt mit einer `read()`-Methode übergeben bekommen:
Code: Alles auswählen
In [17]: f = urllib.urlopen('http://localhost:8090/test.csv')
In [18]: list(csv.reader(f, delimiter=';'))
Out[18]:
[['Daniel', '20 8 0'],
['Daniel', '10 0 0'],
['Daniel', '30 0 0'],
['Lucas', '70 4 0'],
['Lucas', '12 0 0']]
In [19]: f.close()