Seite 1 von 1

Dateien öffnen

Verfasst: Samstag 3. Juli 2010, 15:44
von Py-Prog
Wenn man ein Programm schreibt, das viele dateien öffnet und schreibt, nervt der das unnötige schreiben oft. Deshalb hab ich zwei funktionen geschrieben die das in einem zug machen, und möchte gern wissen was ihr davon haltet:

Code: Alles auswählen

def fileopen(path):
    try:
        f=open(path, 'r')
        dtt=f.read()
        f.close()
        return(dtt)
    except:
        return('Fehler')
und

Code: Alles auswählen

def filesave(path, dateiinhalt):
    try:
        f=open(path, 'w')
        dtt=f.write(dateiinhalt)
        f.close()
    except:
        return('Fehler')

Re: Dateien öffnen

Verfasst: Samstag 3. Juli 2010, 16:05
von BlackJack
@Py-Prog: Ein paar Namen sind falsch. `fileopen()` öffnet zum Beispiel nicht sondern liest ein. Das `datei`-Argument bei `filesave()` ist keine Datei sondern Datei*inhalt*.

Und die Ausnahmebehandlung ist unsinnig. Ausnahmen sollte man nur behandeln wenn man das auch *sinnvoll* tun kann. Eine Ausnahme in einen "speziellen" Rückgabewert verwandeln ist nicht sinnvoll, denn Ausnahmen wurden ja gerade eingeführt um diese speziellen Fehlerwerte loszuwerden. Insbesondere bei `fileopen()` ist der Rückgabewert noch nicht einmal speziell. Wie unterscheide ich denn bitte einen Fehler von einer Textdatei die *tatsächlich* 'Keine Datei' oder 'Fehler' als Text enthält und fehlerfrei gelesen werden konnte!? Zumal 'Keine Datei' bei einem `IOError` unzutreffend sein kann. Ein-/Ausgabefehler können durch eine ganze Reihe von gegebenheiten entstehen, nicht nur wenn die Datei nicht existiert.

Re: Dateien öffnen

Verfasst: Samstag 3. Juli 2010, 16:19
von Py-Prog
BlackJack hat geschrieben:@Py-Prog: Ein paar Namen sind falsch. `fileopen()` öffnet zum Beispiel nicht sondern liest ein. Das `datei`-Argument bei `filesave()` ist keine Datei sondern Datei*inhalt*.
Genau das wolte ich ja.
BlackJack hat geschrieben: Und die Ausnahmebehandlung ist unsinnig. Ausnahmen sollte man nur behandeln wenn man das auch *sinnvoll* tun kann. Eine Ausnahme in einen "speziellen" Rückgabewert verwandeln ist nicht sinnvoll, denn Ausnahmen wurden ja gerade eingeführt um diese speziellen Fehlerwerte loszuwerden. Insbesondere bei `fileopen()` ist der Rückgabewert noch nicht einmal speziell. Wie unterscheide ich denn bitte einen Fehler von einer Textdatei die *tatsächlich* 'Keine Datei' oder 'Fehler' als Text enthält und fehlerfrei gelesen werden konnte!? Zumal 'Keine Datei' bei einem `IOError` unzutreffend sein kann. Ein-/Ausgabefehler können durch eine ganze Reihe von gegebenheiten entstehen, nicht nur wenn die Datei nicht existiert.
Wenn ich die Ausnahmen nicht mache beendet sich das Programm wenn die Datei nicht existiert, und das ist ganz schlecht wenn, ein Das skript keine fehlermeldungen ausgiebt wenn ein fehler unterlaufen ist, weil man dann z. B. denkt die Backups sind ervolgreich abgeschlossen obwohl das Skript sich vorzeitig beendet hat.

Re: Dateien öffnen

Verfasst: Samstag 3. Juli 2010, 16:33
von DasIch

Code: Alles auswählen

~# python -c "raise IOError()" && echo success
Traceback (most recent call last):
  File "<string>", line 1, in <module>
IOError
Es wird eine Fehlermerldung ausgegeben und der Returncode zeigt einen Fehler an, wie kann man da von erfolgreich sprechen?

P.S.: return ist ein Keyword und keine Funktion.

Re: Dateien öffnen

Verfasst: Samstag 3. Juli 2010, 17:08
von BlackJack
@Py-Prog: Was genau wolltest Du ja? Falsche Namen verwenden? Wie unsinnig ist dass denn?

Wenn eine Ausnahme das Programm beendet, dann fehlt eine Ausnahmebehandlung. Aber an der richtigen Stelle und das ist sicher nicht in *den* beiden Funktionen. Das *erhöht* sogar die Gefahr dass ein Programm sich normal beendet obwohl ein Fehler aufgetreten ist, denn genau das ist ja eines der Probleme mit speziellen Fehlerwerten, das man mit Ausnahmen beheben möchte: Es ist nicht mehr so einfach möglich Fehler zu ignorieren. Bei Fehlerwerten ist es ganz einfach den Wert zu ignorieren in dem man einfach keinen Code schreibt, der ihn prüft. Bei Ausnahmen muss man wenigstens aktiv und absichtlich sagen, dass einem der Fehler egal ist, sonst fliegt er einem um die Ohren.

Re: Dateien öffnen

Verfasst: Samstag 3. Juli 2010, 18:27
von Dav1d
Das Schließen der Datei sollte außerdem im finallay erfolgen

Code: Alles auswählen

try:
     f = open(iwas, 'w')
     #bla
finally:
    f.close()
oder gleich mit dem with Statement öffnen

Code: Alles auswählen

with open(iwas, 'w') as f:
    pass

Re: Dateien öffnen

Verfasst: Samstag 3. Juli 2010, 20:51
von EyDu
@Dav1d: Du machst dort zwei verschiedene Dinge:

Code: Alles auswählen

>>> try:
...     f = open(42)
... finally:
...     f.close()
... 
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
NameError: name 'f' is not defined
>>> with open(42) as f:
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: coercing to Unicode: need string or buffer, int found
Beide mögliche Fehlerquellen müssen behandelt werden.

Re: Dateien öffnen

Verfasst: Samstag 3. Juli 2010, 21:05
von lunar
"open" kann und sollte vor den Block gezogen werden. Wenn die Datei nicht geöffnet werden konnte, braucht man auch kein finally, um sie wieder zu schließen. Das ist nur bei Fehlern nötig, die nach dem Öffnen auftreten:

Code: Alles auswählen

stream = open(foo, 'w')
try:
    stream.write('hello world')
finally:
    stream.close()

Re: Dateien öffnen

Verfasst: Samstag 3. Juli 2010, 22:47
von sma
Ich halte es nicht für nötig, das Lesen und Schreiben von Textdateien gesondert als Hilfsfunktionen zu extrahieren, denn die Logik ist so einfach, dass es einfach genug ist, das in jeder Anwendung selbst zu machen. Zudem gilt es häufig besondere Bedürfnisse eines Programms zu beachten und auch das Verhalten, wenn die Datei existiert oder nicht, kann jedes Mal anders sein.

Dass das `return 'Fehler'` keine gute Idee ist, haben schon andere geschrieben. Wenn man's unbedingt in Funktionen gießen will, würde ich folgendes vorschlagen:

Code: Alles auswählen

def file_read(n):
    with open(n, "r") as f: return f.read()

def file_write(n, d):
    with open(n, "w") as f: f.write(d)
Meist ist es aber besser, Textdateien nicht komplett zu lesen, sondern sie zeilenweise zu verarbeiten.

Will man sie nur mal kurz in einem "Wegwerfprogramm" verarbeiten, finde ich es auch akzeptabel, die Ressourcen nicht korrekt zu schließen (passiert bei `with` implizit), sondern sich darauf zu verlassen, dass der CPython-Interpreter das dank Referenz-Zählung selbstständig macht und würde einfach dies benutzen:

Code: Alles auswählen

t = open(n).read()
open(n, "w").write(t)
Dazu sollte man aber die erste korrekte Version verstanden haben.
Stefan

Re: Dateien öffnen

Verfasst: Sonntag 4. Juli 2010, 09:45
von Dav1d
lunar hat geschrieben:"open" kann und sollte vor den Block gezogen werden. Wenn die Datei nicht geöffnet werden konnte, braucht man auch kein finally, um sie wieder zu schließen. Das ist nur bei Fehlern nötig, die nach dem Öffnen auftreten:
EyDu, lunar: Ja, da habt ihr natürlich recht

Re: Dateien öffnen

Verfasst: Montag 5. Juli 2010, 15:14
von Py-Prog
Ist der

Code: Alles auswählen

def fileopen(path):
    f=open(path, 'r')
    dtt=f.read()
    f.close()
    return dtt
    
und der

Code: Alles auswählen

def filesave(path, dateiinhalt):
    f=open(path, 'w')
    dtt=f.write(dateiinhalt)
    f.close()
    
besser als mein erster vorschlag?

Re: Dateien öffnen

Verfasst: Montag 5. Juli 2010, 16:11
von lunar
Unwesentlich. Zwar hast Du die unsinnige Ausnahmebehandlung entfernt, aber korrekt geschlossen werden die Dateien im Falle einer Ausnahme noch immer nicht.

Und letztlich hat sma recht. Das ist viel zu trivial, um eine eigene Hilfsfunktion zu rechtfertigen.

Re: Dateien öffnen

Verfasst: Freitag 16. Juli 2010, 15:31
von Py-Prog
Ihr hattet recht, mit dieser

Code: Alles auswählen

return 'Fehler'
anweisung sucht man den fehler an der faltschen stelle.

Re: Dateien öffnen

Verfasst: Freitag 16. Juli 2010, 15:37
von jbs
Stell dir mal vor, die Datei enthält Fehler! ;)