wake-up-neo.com

python versuchen: außer: endlich

# Open new file to write
file = None
try:
    file = open(filePath, 'w')
except IOError:
    msg = ("Unable to create file on disk.")
    file.close()
    return
finally:
    file.write("Hello World!")
    file.close()

Der obige Code wird von einer Funktion gerissen. Ein System des Benutzers meldet einen Fehler in der Zeile:

file.write("Hello World!")

error:

AttributeError: 'NoneType' object has no attribute 'write'

Die Frage ist, wenn der Python die angegebene Datei nicht öffnen kann, wird der Block 'except' ausgeführt und er muss Return zurückgeben, die Kontrolle wird jedoch an die Zeile übergeben, in der der Fehler ausgegeben wird. Der Wert der 'file'-Variablen ist' None '.

Irgendwelche Hinweise?

35
user354051

Sie sollten nicht in die Datei im finally-Block schreiben, da dort auftretende Ausnahmen nicht vom except-Block erfasst werden.

Der except-Block wird ausgeführt, wenn vom try-Block eine Ausnahme ausgelöst wird. Der finally-Block always führt aus, was auch immer geschieht.

Es sollte auch keine Notwendigkeit bestehen, die Variable file auf none zu initialisieren.

Die Verwendung von return im except-Block überspringt den finally-Block nicht. Es kann von Natur aus nicht übersprungen werden, deshalb möchten Sie Ihren "Bereinigungs" -Code dort einfügen (d. H. Dateien schließen).

Wenn Sie also versuchen möchten, versuchen Sie Folgendes: Ausnahmen: Schließlich sollten Sie Folgendes tun:

try:
    f = open("file", "w")
    try:
        f.write('Hello World!')
    finally:
        f.close()
except IOError:
    print 'oops!'

Eine viel sauberere Methode hierfür ist die Verwendung der Anweisung with:

try:
    with open("output", "w") as outfile:
        outfile.write('Hello World')
except IOError:
    print 'oops!'
84
Acorn

Wenn die Datei nicht geöffnet ist, schlägt die Zeile file = open(filePath, 'w') fehl, sodass file nichts zugewiesen wird.

Dann wird die except-Klausel ausgeführt, aber es ist nichts in der Datei, daher schlägt file.close() fehl.

Die finally-Klausel wird immer ausgeführt, auch wenn eine Ausnahme vorliegt. Und da file immer noch None ist, erhalten Sie eine weitere Ausnahme.

Sie möchten eine else-Klausel anstelle von finally für Dinge, die nur dann passieren, wenn keine Ausnahme vorliegt.

    try:
        file = open(filePath, 'w')
    except IOError:
        msg = "Unable to create file on disk."
        return
    else:
        file.write("Hello World!")
        file.close()

Warum das else? Die Python-Dokumente sagen: 

Die else-Klausel ist besser zu verwenden, als der try-Klausel zusätzlichen Code hinzuzufügen, da dadurch versehentlich eine Ausnahme nicht erkannt wird, die nicht durch den durch die try ... except-Anweisung geschützten Code ausgelöst wurde.

Mit anderen Worten, dies wird keine IOError von den write- oder close-Aufrufen abfangen. Das ist gut so, denn dann gab es keine Gründe, warum keine Datei auf der Festplatte erstellt werden konnte. Dies wäre ein anderer Fehler gewesen, für den Ihr Code nicht vorbereitet war. Es ist eine gute Idee, nicht mit solchen Fehlern umgehen zu wollen.

27
Petr Viktorin

was ist die Logik bei der Einbeziehung der

file.write("Hello World!")

innerhalb der finally -Klausel ?? Ich denke, es muss in try Klausel selbst gestellt werden.

try:
        file = open(filePath, 'w')
        file.write("Hello World!")
except IOError:
        print("Unable to create file on disk.")
finally:
        file.close()
4
Sreenath Nannat

Hier ist die direkteste Lösung für Ihr Problem. Ich benutze das Idiom der Suche nach file_obj != None im finally-Block. 

Übrigens sollten Sie wissen, dass file ein Python-Klassenname ist. Sie sollten also einen anderen Variablennamen wählen.

file = None
try:
    file = open(filePath, 'w')
except IOError:
    msg = ("Unable to create file on disk.")
    file.close()
    return
finally:
    if file != None:
        file.write("Hello World!")
        file.close()

außer es wird nicht ausgeführt (weil der Typ IOError ist). Der letzte Teil löst einen anderen Fehler des Typs AttributeError aus, da file = None ist.

1
TigOldBitties

Sie können so etwas tun:

try:
    do_some_stuff()
finally:
    cleanup_stuff()
1
user5578789

wird schließlich immer am "Ende" aufgerufen, auch wenn eine Ausnahme auftritt. Sie können dies verwenden, um sicherzustellen, dass offene Ressourcen geschlossen sind (z. B. eine DB-Verbindung, eine Datei usw.).

Ich denke, Sie haben die Semantik missverstanden.

Ihre Logik sollte im "try" sein, Sie sollten sich mit Ausnahmen im "außer" -Block befassen, und "final" wird ausgeführt, egal wie Ihre Methode beendet wird.

0
pcalcao