So ignorieren Sie Ausnahmen richtig


777

Wie machen Sie es in Python, wenn Sie nur einen Versuch ausführen möchten, ohne die Ausnahme zu behandeln?

Ist das Folgende der richtige Weg, um es zu tun?

try:
    shutil.rmtree(path)
except:
    pass

10
Seltsam, dass es bis jetzt niemand erwähnt hat (das habe ich in meiner Antwort getan), aber für diese spezielle Funktion können Sie es einfach tun shutil.rmtree(path, ignore_errors=True). Dies gilt jedoch nicht für die meisten Funktionen.
Aaron Hall

9
Wichtige Lektüre beim Überlegen, Ausnahmen zu ignorieren: Warum ist „Ausnahme: Bestehen“ eine schlechte Programmierpraxis?
stupsen

3
Stellen Sie sich vor, Sie tun dies im wirklichen Leben. versuchen Sie: get_cash ('$ 1000') außer: pass # meh, es wird wahrscheinlich in Ordnung sein
Grokodile

Reales Leben:try: rob() except: run()
PatrickT vor

Antworten:


1039
try:
    doSomething()
except: 
    pass

oder

try:
    doSomething()
except Exception: 
    pass

Der Unterschied ist , dass die erste, wird auch fangen KeyboardInterrupt, SystemExitund so wie die, die direkt aus abgeleitet sind exceptions.BaseException, nicht exceptions.Exception.

Einzelheiten finden Sie in der Dokumentation:


4
Beachten Sie, dass StopIteration und Warning ebenfalls von Exception erben. Abhängig von Ihren Anforderungen möchten Sie möglicherweise stattdessen von StandardError erben.
Ben Blank

1
Dies ist wahr, aber wenn Sie nicht vorsichtig sind, können subtile Fehler auftreten (insbesondere, wenn Sie etwas anderes tun als StopIteration weiterzugeben).
Jason Baker

17
-1, try: shuti.rmtree(...) except: passwird grob alle Fehler unterdrücken (auch wenn Sie falsch schreiben, shutilwas zu a führt NameError) - zumindest tunexcept OSError:
dbr

44
Diese Antwort ist zwar informativ, es fehlen jedoch wichtige Informationen. Auf diese Weise sollten Sie niemals eine Ausnahme einfangen. Stattdessen sollten Sie immer versuchen, nur die Ausnahmen zu erfassen, die Ihnen wichtig sind. Andernfalls treten bei der Suche nach trivialen Fehlern Albträume auf, die durch Ihre generischen "Ausnahmen" verborgen sind. Weitere Informationen finden Sie in der Antwort von dbr. (Ich weiß, dass dies nicht die ursprüngliche Frage war - aber jeder, der danach sucht, nimmt einfach Ihr Snippet und verwendet es so wie es ist)
Johndodo

139

Es ist im Allgemeinen am besten Praxis nur dann in Betracht , die Fehler fangen Sie interessiert sind im Falle von. shutil.rmtreeEs ist wahrscheinlich OSError:

>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
    [...]
OSError: [Errno 2] No such file or directory: '/fake/dir'

Wenn Sie diesen Fehler stillschweigend ignorieren möchten, gehen Sie wie folgt vor:

try:
    shutil.rmtree(path)
except OSError:
    pass

Warum? Angenommen, Sie übergeben der Funktion (irgendwie) versehentlich eine Ganzzahl anstelle einer Zeichenfolge, wie z.

shutil.rmtree(2)

Es wird der Fehler "TypeError: Erzwingen zu Unicode: Benötige Zeichenfolge oder Puffer, int gefunden" geben - Sie möchten das wahrscheinlich nicht ignorieren, was schwierig zu debuggen sein kann.

Wenn Sie definitiv alle Fehler ignorieren möchten, fangen Sie Exceptioneher als eine bloße except:Aussage. Wieder warum?

Wenn Sie keine Ausnahme angeben, werden alle Ausnahmen abgefangen , einschließlich der SystemExitAusnahme, die beispielsweise sys.exit()Folgendes verwendet:

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>

Vergleichen Sie dies mit dem folgenden, das korrekt beendet wird:

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
shell:~$ 

Wenn Sie immer besser verhaltenen Code schreiben möchten, kann die OSErrorAusnahme verschiedene Fehler darstellen. Im obigen Beispiel möchten wir sie jedoch nur ignorieren Errno 2, sodass wir noch spezifischer sein können:

import errno

try:
    shutil.rmtree(path)
except OSError as e:
    if e.errno != errno.ENOENT:
        # ignore "No such file or directory", but re-raise other errors
        raise

1
shutil.rmtreeist nicht das beste Beispiel, weil Sie nur ignore_errors=Truefür diese Funktion verwenden würden ..
wim

113

Wie machen Sie es in Python, wenn Sie nur einen Try-Catch ausführen möchten, ohne die Ausnahme zu behandeln?

Es hängt davon ab, was Sie unter "Handhabung" verstehen.

Wenn Sie es abfangen möchten, ohne etwas zu unternehmen, funktioniert der von Ihnen veröffentlichte Code.

Wenn Sie damit meinen, dass Sie für eine Ausnahme Maßnahmen ergreifen möchten, ohne die Ausnahme daran zu hindern, den Stapel zu erhöhen, möchten Sie Folgendes:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown

88

Zuerst zitiere ich die Antwort von Jack o'Connor aus diesem Thread . Der Thread, auf den verwiesen wird, wurde geschlossen, also schreibe ich hier:

"In Python 3.4 gibt es eine neue Möglichkeit, dies zu tun:

from contextlib import suppress

with suppress(Exception):
    # your code

Hier ist das Commit, das es hinzugefügt hat: http://hg.python.org/cpython/rev/406b47c64480

Und hier ist der Autor Raymond Hettinger, der über diese und alle möglichen anderen Python-Hotness spricht: https://youtu.be/OSGv2VnC0go?t=43m23s

Meine Ergänzung dazu ist das Python 2.7-Äquivalent:

from contextlib import contextmanager

@contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass

Dann verwenden Sie es wie in Python 3.4:

with ignored(Exception):
    # your code

55

Zur Vollständigkeit:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")

Beachten Sie auch, dass Sie die Ausnahme folgendermaßen erfassen können:

>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print("Handling run-time error:", err)

... und die Ausnahme wie folgt erneut auslösen:

>>> try:
...     raise NameError('HiThere')
... except NameError:
...     print('An exception flew by!')
...     raise

... Beispiele aus dem Python-Tutorial .


43

Wie ignoriere ich Ausnahmen richtig?

Es gibt verschiedene Möglichkeiten, dies zu tun.

Die Wahl des Beispiels hat jedoch eine einfache Lösung, die den allgemeinen Fall nicht abdeckt.

Spezifisch für das Beispiel:

Anstatt

try:
    shutil.rmtree(path)
except:
    pass

Mach das:

shutil.rmtree(path, ignore_errors=True)

Dies ist ein spezifisches Argument für shutil.rmtree. Sie können die Hilfe dazu wie folgt anzeigen, und Sie werden sehen, dass sie auch Funktionen für Fehler zulässt.

>>> import shutil
>>> help(shutil.rmtree)

Da dies nur den engen Fall des Beispiels abdeckt, werde ich weiter demonstrieren, wie damit umgegangen wird, wenn diese Schlüsselwortargumente nicht vorhanden waren.

Allgemeiner Ansatz

Da das Obige nur den engen Fall des Beispiels abdeckt, werde ich weiter demonstrieren, wie damit umgegangen wird, wenn diese Schlüsselwortargumente nicht vorhanden waren.

Neu in Python 3.4:

Sie können den suppressKontextmanager importieren :

from contextlib import suppress

Aber unterdrücken Sie nur die spezifischste Ausnahme:

with suppress(FileNotFoundError):
    shutil.rmtree(path)

Sie werden stillschweigend ignorieren FileNotFoundError:

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 

Aus den Dokumenten :

Wie bei jedem anderen Mechanismus, der Ausnahmen vollständig unterdrückt, sollte dieser Kontextmanager nur verwendet werden, um sehr spezifische Fehler abzudecken, bei denen es bekanntermaßen richtig ist, die Programmausführung stillschweigend fortzusetzen.

Beachten Sie, dass suppressund FileNotFoundErrornur in Python 3 verfügbar sind.

Wenn Sie möchten, dass Ihr Code auch in Python 2 funktioniert, lesen Sie den nächsten Abschnitt:

Python 2 & 3:

Wie machen Sie es in Python, wenn Sie nur versuchen / ausnehmen möchten, ohne die Ausnahme zu behandeln?

Ist das Folgende der richtige Weg, um es zu tun?

try :
    shutil.rmtree ( path )
except :
    pass

Für Python 2-kompatiblen Code passist dies der richtige Weg, um eine Anweisung zu erhalten, die kein Op ist. Aber wenn man mit einem nackten tun except:, das ist die gleiche wie zu tun , except BaseException:was beinhaltet GeneratorExit, KeyboardInterruptund SystemExit, und im Allgemeinen, Sie wollen nicht , diese Dinge zu fangen.

Tatsächlich sollten Sie die Ausnahme so genau wie möglich benennen.

Hier ist ein Teil der Python (2) -Ausnahmehierarchie . Wie Sie sehen, können Sie Probleme verbergen, die Sie nicht erwartet haben, wenn Sie allgemeinere Ausnahmen abfangen:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
... and so on

Sie möchten hier wahrscheinlich einen OSError abfangen, und vielleicht ist die Ausnahme, die Sie nicht interessiert, wenn kein Verzeichnis vorhanden ist.

Wir können diese spezifische Fehlernummer aus der errnoBibliothek abrufen und erneut erhöhen, wenn wir diese nicht haben:

import errno

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno == errno.ENOENT: # no such file or directory
        pass
    else: # we had an OSError we didn't expect, so reraise it
        raise 

Beachten Sie, dass eine bloße Erhöhung die ursprüngliche Ausnahme auslöst, was in diesem Fall wahrscheinlich das ist, was Sie wollen. Genauer geschrieben, da wir passbei der Ausnahmebehandlung nicht explizit mit Code arbeiten müssen:

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno != errno.ENOENT: # no such file or directory
        raise 

11

Wie machen Sie es in Python, wenn Sie nur einen Try-Catch ausführen möchten, ohne die Ausnahme zu behandeln?

Dies hilft Ihnen beim Drucken der Ausnahme: (dh versuchen Sie catch, ohne die Ausnahme zu behandeln, und drucken Sie die Ausnahme.)

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]

10
try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

Zu Ihrer Information, die else-Klausel kann nach allen Ausnahmen gehen und wird nur ausgeführt, wenn der Code im Versuch keine Ausnahme verursacht.


1
Zum Schluss noch eine gute Erklärung elsein diesem Zusammenhang. Und um das hinzuzufügen, finallywird immer nach einer (oder keiner Ausnahme) ausgeführt.
not2qubit

5

Ich musste Fehler in mehreren Befehlen ignorieren und fuckit hat den Trick gemacht

import fuckit

@fuckit
def helper():
    print('before')
    1/0
    print('after1')
    1/0
    print('after2')

helper()

+1, weil du definitiv meinen Tag gemacht hast, weil du in diesem Quellcode einige äußerst nützliche Dinge lernen kannst, wie das Ändern des Live-Stacks
WBAR

3

In Python behandeln wir Ausnahmen, die denen anderer Sprachen ähnlich sind, aber der Unterschied ist ein Syntaxunterschied, z.

try:
    #Your code in which exception can occur
except <here we can put in a particular exception name>:
    # We can call that exception here also, like ZeroDivisionError()
    # now your code
# We can put in a finally block also
finally:
    # Your code...

-4

Normalerweise mache ich einfach:

try:
    doSomething()
except:
    _ = ""

3
Ich würde vorschlagen , dass Sie ersetzen _ = ""mit pass.
Legorooj
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.