Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 3110 – Ausnahmen in Python 3000 abfangen

Autor:
Collin Winter <collinwinter at google.com>
Status:
Final
Typ:
Standards Track
Erstellt:
16. Jan 2006
Python-Version:
3.0
Post-History:


Inhaltsverzeichnis

Zusammenfassung

Diese PEP führt Änderungen ein, die darauf abzielen, Mehrdeutigkeiten in der Grammatik von Python zu beseitigen, Ausnahme-Klassen zu vereinfachen, die Garbage Collection für Ausnahmen zu vereinfachen und die Größe der Sprache in Python 3.0 zu reduzieren.

Begründung

  1. except-Klauseln in Python 2.x weisen eine syntaktische Mehrdeutigkeit auf, bei der der Parser nicht unterscheiden kann, ob
    except <expression>, <expression>:
    

    als

    except <type>, <type>:
    

    oder

    except <type>, <name>:
    

    interpretiert werden soll. Python 2 entscheidet sich für die letztere Semantik, auf Kosten der Notwendigkeit, erstere mit Klammern zu versehen, wie folgt:

    except (<type>, <type>):
    
  2. Wie in PEP 352 spezifiziert, wird die Fähigkeit, Ausnahmen als Tupel zu behandeln, entfernt, was bedeutet, dass dieser Code nicht mehr funktioniert.
    except os.error, (errno, errstr):
    

    Da die automatische Entpackung nicht mehr möglich ist, ist es wünschenswert, die Möglichkeit, Tupel als except-Ziele zu verwenden, zu entfernen.

  3. Wie in PEP 344 spezifiziert, werden Ausnahmen-Instanzen in Python 3 ein __traceback__-Attribut besitzen. Der Abschnitt "Offene Fragen" dieser PEP enthält einen Absatz über Garbage Collection-Schwierigkeiten, die durch dieses Attribut verursacht werden, nämlich einen Referenzzyklus "exception -> traceback -> stack frame -> exception", wodurch alle lokalen Variablen bis zum nächsten GC-Lauf im Gültigkeitsbereich gehalten werden. Diese PEP beabsichtigt, dieses Problem zu lösen, indem sie eine Bereinigungssemantik zu except-Klauseln in Python 3 hinzufügt, bei der der Zielname am Ende der except-Suite gelöscht wird.
  4. Im Geiste von „Es sollte eine – und vorzugsweise nur eine – offensichtliche Art geben, dies zu tun“ ist es wünschenswert, doppelte Funktionalität zu konsolidieren. Zu diesem Zweck werden die Attribute exc_value, exc_type und exc_traceback des sys-Moduls [1] zugunsten von sys.exc_info() entfernt, das die gleichen Informationen liefert. Diese Attribute sind bereits in PEP 3100 als zur Entfernung vorgesehene aufgeführt.

Grammatikänderungen

In Python 3 ändert sich die Grammatik für except-Anweisungen von [4]

except_clause: 'except' [test [',' test]]

zu

except_clause: 'except' [test ['as' NAME]]

Die Verwendung von as anstelle des Komma-Tokens bedeutet, dass

except (AttributeError, os.error):

klar als Tupel von Ausnahme-Klassen verstanden werden kann. Diese neue Syntax wurde erstmals von Greg Ewing [2] vorgeschlagen und vom BDFL ([2], [3]) gutgeheißen.

Darüber hinaus beschränkt die Einschränkung des Tokens nach as von test auf NAME, dass nur gültige Bezeichner als except-Ziele verwendet werden können.

Beachten Sie, dass die obige Grammatik immer geklammerte Tupel als Ausnahme-Klassen verlangt. So kann die mehrdeutige

except A, B:

die in Python 2.x und 3.x unterschiedliche Bedeutungen hätte – was zu schwer zu findenden Fehlern führt – in 3.x-Code nicht mehr legal auftreten.

Semantische Änderungen

Um das Garbage Collection-Problem im Zusammenhang mit PEP 344 zu lösen, werden except-Anweisungen in Python 3 zusätzlichen Bytecode generieren, um das Ziel zu löschen, wodurch der Referenzzyklus eliminiert wird. Die Quellcode-zu-Quellcode-Übersetzung, wie von Phillip J. Eby [5] vorgeschlagen, ist

try:
    try_body
except E as N:
    except_body
...

wird übersetzt in (in Python 2.5 Begriffen)

try:
    try_body
except E, N:
    try:
        except_body
    finally:
        N = None
        del N
...

Eine Implementierung wurde bereits in den py3k-Branch (früher „p3yk“) eingecheckt [6].

Kompatibilitätsprobleme

Fast alle except-Klauseln müssen geändert werden. except-Klauseln mit Bezeichner-Zielen werden von

except E, N:

zu

except E as N:

except-Klauseln mit Nicht-Tupel-, Nicht-Bezeichner-Zielen (z. B. a.b.c[d]) müssen von

except E, T:

zu

except E as t:
    T = t

Beide Fälle können mit dem 2to3-Dienstprogramm von Guido van Rossum [7] mithilfe des except-Fixers [8] behandelt werden.

except-Klauseln mit Tupel-Zielen müssen manuell, von Fall zu Fall, konvertiert werden. Diese Änderungen müssen normalerweise von Änderungen an den Ausnahme-Klassen selbst begleitet werden. Obwohl diese Änderungen im Allgemeinen nicht automatisiert werden können, ist das 2to3-Dienstprogramm in der Lage, Fälle zu identifizieren, in denen das Ziel einer except-Klausel ein Tupel ist, was die Konvertierung vereinfacht.

Situationen, in denen es notwendig ist, eine Ausnahmen-Instanz über das Ende der except-Suite hinaus beizubehalten, können wie folgt leicht übersetzt werden:

try:
    ...
except E as N:
    ...
...

wird zu

try:
    ...
except E as N:
    n = N
    ...
...

Auf diese Weise wird, wenn N am Ende des Blocks gelöscht wird, n beibehalten und kann wie gewohnt verwendet werden.

Schließlich müssen alle Verwendungen der Attribute exc_type, exc_value und exc_traceback des sys-Moduls entfernt werden. Sie können durch sys.exc_info()[0], sys.exc_info()[1] bzw. sys.exc_info()[2] ersetzt werden, eine Transformation, die von 2to3's sysexcattrs fixer durchgeführt werden kann.

2.6 - 3.0 Kompatibilität

Um die Vorwärtskompatibilität zwischen Python 2.6 und 3.0 zu gewährleisten, wird die except ... as ...:-Syntax in die 2.x-Serie zurückportiert. Die Grammatik ändert sich somit von

except_clause: 'except' [test [',' test]]

zu

except_clause: 'except' [test [('as' | ',') test]]

Die Bereinigungssemantik am Ende der Suite für except-Anweisungen wird nicht in die 2.x-Serie der Veröffentlichungen aufgenommen.

Offene Fragen

Ersetzen oder Entfernen von „sys.exc_info()“

Die Idee, sys.exc_info() zu entfernen oder durch ein sys.exception-Attribut oder eine sys.get_exception()-Funktion zu ersetzen, wurde mehrmals auf python-3000 ([9], [10]) diskutiert und im Abschnitt "Offene Fragen" von PEP 344 erwähnt.

Obwohl ein 2to3-Fixer zum Ersetzen von Aufrufen von sys.exc_info() und einigen Attributzugriffen trivial wäre, wäre es für die statische Analyse wesentlich schwieriger, Funktionen zu finden und zu korrigieren, die die Werte von sys.exc_info() als Argumente erwarten. Ebenso behebt dies nicht die Notwendigkeit, die Dokumentation für alle APIs neu zu schreiben, die im Hinblick auf sys.exc_info() definiert sind.

Implementierung

Diese PEP wurde in den Revisionen 53342 [11] und 53349 [12] implementiert. Die Unterstützung für die neue except-Syntax in 2.6 wurde in Revision 55446 [13] implementiert.

Referenzen


Quelle: https://github.com/python/peps/blob/main/peps/pep-3110.rst

Zuletzt geändert: 2025-02-01 08:59:27 GMT