2016-08-03 24 views
14

Die Referenzzustände Python Sprache in section 7.4:Warum fängt außer object alles in Python ein?

Für eine except-Klausel mit einem Ausdruck, wird dieser Ausdruck ausgewertet, und die Klausel entspricht die Ausnahme, wenn das resultierende Objekt „kompatibel“ mit der Ausnahme ist. Ein Objekt ist kompatibel mit einer Ausnahme, wenn es sich um die Klasse oder eine Basisklasse des Ausnahmeobjekts handelt, oder ein Tupel, das ein Element enthält, das mit der Ausnahme kompatibel ist.

Also, warum nicht except object: alles fangen? object ist die Basisklasse aller Ausnahmeklassen, daher sollte except object: jede Ausnahme abfangen können.

Zum Beispiel sollten diese fangen die AssertionError

print isinstance(AssertionError(), object) # prints True 
try: 
    raise AssertionError() 
except object: 
    # This block should execute but it never does. 
    print 'Caught exception' 
+4

Sie benötigen eine Ausnahme dort geben zu setzen, und 'object' ist keine Ausnahme Art. Ich bin mir nicht sicher, warum das nicht einen 'TypeError' auslöst. – user2357112

+1

Das funktioniert übrigens nur in 2.x. In 3.x wird ein TypeError ausgelöst. Meine Annahme wäre, dass es aufgrund einer fehlenden magischen Methode fehlschlägt, aber ich konnte Ihnen nicht sagen, welche (s). 'AssertionError' hat das folgende Attribut, dass' Objekt' nicht '{'__setstate__', 'args', '__context__', '__suppress_context__','__dict__ ','__cause__', 'with_traceback','__traceback__}}' hat , also nehme ich an, es liegt an einem von denen. –

+3

Sieht aus wie ein Fehler in der 2.x-Ausnahmebehandlung. Python 3 verfügt über die richtige Prüfung, um Nicht-Ausnahme-Typen abzufangen. Python 2 macht einfach nur das Falsche. – user2357112

Antwort

3

Ich glaube, die Antwort kann in den source code for python 2.7 finden:

 else if (Py_Py3kWarningFlag && 
       !PyTuple_Check(w) && 
       !Py3kExceptionClass_Check(w)) 
     { 
      int ret_val; 
      ret_val = PyErr_WarnEx(
       PyExc_DeprecationWarning, 
       CANNOT_CATCH_MSG, 1); 
      if (ret_val < 0) 
       return NULL; 
     } 

also, wenn w (ich nehme den Ausdruck in der except-Anweisung) ist keine Tuple oder Exception-Klasse und die Py_Py3kWarningFlag wird dann versucht, einen ungültigen Ausnahme-Typ in der Ausnahme zu verwenden, wird Block eine Warnung anzeigen Ing.

Diese Flagge, indem Sie die -3-Flag gesetzt ist, wenn Sie Ihre Datei ausführen:

Tadhgs-MacBook-Pro:~ Tadhg$ python2 -3 /Users/Tadhg/Documents/codes/test.py 
True 
/Users/Tadhg/Documents/codes/test.py:5: DeprecationWarning: catching classes that don't inherit from BaseException is not allowed in 3.x 
    except object: 
Traceback (most recent call last): 
    File "/Users/Tadhg/Documents/codes/test.py", line 4, in <module> 
    raise AssertionError() 
AssertionError 
+0

Es fällt nicht in den Standardfall; Es geht zu 'PyErr_GivenExceptionMatches (v, w)', was dazu führt, dass der alte Codepfad für jetzt entfernte Zeichenfolgenausnahmen verwendet wird. – user2357112

+0

Ja, das habe ich nach einem längeren Blick auf den Code bemerkt.Ich dachte mir, eine schlechte/ungenaue Antwort mit Links zu dem definitiv relevanten Code zu veröffentlichen, war es wert, gepostet zu werden, damit Leute wie du mich korrigieren können: D –

+0

Seltsamerweise scheint Python 2 so ziemlich alles für einen 'ausgenommen' Ausdruck zu setzen, aber es verhält sich stillschweigend im Widerspruch zur Dokumentation, wenn Sie ihr einen Typ geben, der kein Ausnahmetyp ist. Die Dokumentation sollte zumindest aktualisiert werden, obwohl es in Pythons aktuellem Maintenance-Only-Zustand wahrscheinlich nicht sinnvoll ist, etwas an dem Verhalten vorzunehmen. – user2357112