Was ist ein guter Weg, um Ausnahmen zu behandeln, wenn Sie versuchen, eine Datei in Python zu lesen?

84

Ich möchte eine CSV-Datei in Python lesen.

  • Ich weiß nicht, ob die Datei existiert.
  • Meine aktuelle Lösung ist unten. Es fühlt sich für mich schlampig an, weil die beiden separaten Ausnahmetests unangenehm nebeneinander stehen.

Gibt es einen schöneren Weg, dies zu tun?

import csv    
fName = "aFile.csv"

try:
    with open(fName, 'rb') as f:
        reader = csv.reader(f)
        for row in reader:
            pass #do stuff here
    
except IOError:
    print "Could not read file:", fName
Charles Holbrow
quelle
Wenn eine nicht vorhandene Datei kein Fehlerfall, sondern ein wahrscheinlicher Umstand ist, kann es sich lohnen, ihre Abwesenheit / Nichtlesbarkeit explizit vor (und zusätzlich zu) der tryzu überprüfen und zu behandeln . Dies kann mit durchgeführt werden os.path.exists(file)und os.access(file, os.R_OK)sind. Eine solche Überprüfung kann niemals frei von einer Rennbedingung sein, aber das Verschwinden von Dateien ist selten ein normaler Umstand;)
stefanct
2
Die Antworten auf diese Frage sollten wahrscheinlich aktualisiert werden, um die Verwendung des pathlibModuls einzuschließen, was dieses Problem erheblich erleichtert, und sollten wahrscheinlich die Standardpraxis von Python sein (zumal es auch auf 2.7 zurückportiert wurde).
Rick unterstützt Monica
Während dies abfängt IOError, wird es nicht abgefangen, csv.Errorda die Datei nicht im CSV-Format vorliegt, wenn Dialect.strict=Trueoder Errorfür andere Fehler (gemäß CSV-Paketdokumenten). Wenn also ein äußerer Versuch oder einfach nur nach Dateien gesucht wird, ist ein innerer Versuch für CSV-Ausnahmen wahrscheinlich die richtige Antwort.
Pink Spikyhairman
@pinkspikyhairman Ja, in Ihrem Ausnahme-Handler müssen Sie entscheiden, welche Fehlertypen Sie behandeln möchten. Hier erfahren Sie,
Charles Holbrow

Antworten:

50

Ich glaube, ich habe falsch verstanden, was gefragt wurde. Beim erneuten Lesen sieht es so aus, als ob Tims Antwort genau das ist, was Sie wollen. Lassen Sie mich jedoch nur Folgendes hinzufügen: Wenn Sie eine Ausnahme von abfangen möchten open, openmuss dies in a eingeschlossen werden try. Befindet sich der Aufruf von openin der Kopfzeile von a with, withmuss sich der in a befinden try, um die Ausnahme abzufangen. Daran führt kein Weg vorbei.

Die Antwort lautet also entweder: "Tims Weg" oder "Nein, du machst es richtig."


Vorherige nicht hilfreiche Antwort, auf die sich alle Kommentare beziehen:

import os

if os.path.exists(fName):
   with open(fName, 'rb') as f:
       try:
           # do stuff
       except : # whatever reader errors you care about
           # handle error

jscs
quelle
21
Nur weil eine Datei existiert, heißt das nicht, dass Sie sie lesen können!
Gabe
3
Dies ist nicht perfekt, da die Datei möglicherweise (z. B. durch einen anderen Prozess) zwischen der Überprüfung ihrer Existenz und dem Versuch, sie zu öffnen, gelöscht wird.
Liquid_Fire
Vielleicht verstehe ich die Frage falsch. In der Tat denke ich, dass ich definitiv bin.
Jscs
1
Es ist auch möglich, dass fNamedies der Name einer Datei ist, die, selbst wenn sie bestehen bleibt, aus irgendeinem Grund nicht geöffnet werden kann - zum Beispiel, wenn es sich um ein Verzeichnis handelt oder keine Berechtigungen zum Lesen durch den ausführenden Prozess vorhanden sind.
Intuition
4
Die Methode "Wenn vorhanden (Datei): Öffnen (Datei)" kann fehlschlagen, da die Datei entfernt werden kann, nachdem Sie überprüft haben, ob sie vorhanden ist, aber bevor Sie sie öffnen. Oder es könnte gesperrt sein oder keine Leseberechtigung haben oder eine Art Objekt sein, das Sie nicht lesen können (wie ein Verzeichnis) oder auf Band archiviert werden und das Band ist nicht verfügbar, oder es könnte ein Festplattenfehler vorliegen versuchen, die Datei zu öffnen, oder ...
Gabe
62

Wie wäre es damit:

try:
    f = open(fname, 'rb')
except OSError:
    print "Could not open/read file:", fname
    sys.exit()

with f:
    reader = csv.reader(f)
    for row in reader:
        pass #do stuff here
Tim Pietzcker
quelle
10
Das einzige Problem dabei ist, dass die Datei außerhalb des withBlocks geöffnet wird . Wenn also eine Ausnahme zwischen dem tryBlock mit dem Aufruf von openund der withAnweisung auftritt , wird die Datei nicht geschlossen. In diesem Fall, in dem die Dinge sehr einfach sind, ist dies kein offensichtliches Problem, aber es kann dennoch eine Gefahr darstellen, wenn der Code überarbeitet oder auf andere Weise geändert wird. Davon abgesehen glaube ich nicht, dass es einen besseren Weg gibt, dies zu tun (außer der Originalversion).
Intuition
2
@intuited: Das stimmt. Tatsächlich lautet die endgültige Antwort auf das OP wahrscheinlich nur: Nein, die Art und Weise, wie Sie es getan haben, ist die richtige.
Jscs
1
FileNotFoundError.mro() ist [<class 'FileNotFoundError'>, <class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>]und IOError.mro()ist [<class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>]. Wie wäre es entweder OSErroroder Exceptionstattdessen? `` `
hotohoto
1
@hotohoto: Gute Idee. Ich bin mir nicht sicher - vielleicht hat sich die Ausnahmehierarchie in dieser Hinsicht seit 2011 geändert, aber Ihr Vorschlag ist dennoch umfassender.
Tim Pietzcker
16

Hier ist ein Lese- / Schreibbeispiel. Die with-Anweisungen stellen sicher, dass die close () -Anweisung vom Dateiobjekt aufgerufen wird, unabhängig davon, ob eine Ausnahme ausgelöst wird. http://effbot.org/zone/python-with-statement.htm

import sys

fIn = 'symbolsIn.csv'
fOut = 'symbolsOut.csv'

try:
   with open(fIn, 'r') as f:
      file_content = f.read()
      print "read file " + fIn
   if not file_content:
      print "no data in file " + fIn
      file_content = "name,phone,address\n"
   with open(fOut, 'w') as dest:
      dest.write(file_content)
      print "wrote file " + fOut
except IOError as e:
   print "I/O error({0}): {1}".format(e.errno, e.strerror)
except: #handle other exceptions such as attribute errors
   print "Unexpected error:", sys.exc_info()[0]
print "done"
edW
quelle
0
fname = 'filenotfound.txt'
try:
    f = open(fname, 'rb')
except FileNotFoundError:
    print("file {} does not exist".format(fname))

file filenotfound.txt does not exist

Ausnahme FileNotFoundError Wird ausgelöst, wenn eine Datei oder ein Verzeichnis angefordert wird, aber nicht vorhanden ist. Entspricht errno ENOENT.

https://docs.python.org/3/library/exceptions.html
Diese Ausnahme ist in Python 2 nicht vorhanden.

Lou Pendley
quelle
1
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Donald Duck
-11

Hinzufügen zu @ Joshs Beispiel;

fName = [FILE TO OPEN]
if os.path.exists(fName):
    with open(fName, 'rb') as f:
        #add you code to handle the file contents here.
elif IOError:
    print "Unable to open file: "+str(fName)

Auf diese Weise können Sie versuchen, die Datei zu öffnen. Wenn sie jedoch nicht vorhanden ist (wenn ein IOError ausgelöst wird), benachrichtigen Sie den Benutzer!

Zac Brown
quelle
Das Problem nicht sehen. Wenn es sich um eine falsche Syntax handelt, wird bei der Ausführung ein Syntaxfehler ausgelöst!
Zac Brown
7
Kein Syntaxfehler, aber bool(IOError)einfach Trueund ifohne Ausnahme.
8
>>> if IOError: print "That's not an exception handler"
Jscs
3
@ Josh Caswell ist richtig. IOError wird als True ausgewertet. docs.python.org/2.4/lib/truth.html
hecvd