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:
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
except-Klauseln in Python 2.x weisen eine syntaktische Mehrdeutigkeit auf, bei der der Parser nicht unterscheiden kann, obexcept <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>):
- 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. - 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 zuexcept-Klauseln in Python 3 hinzufügt, bei der der Zielname am Ende derexcept-Suite gelöscht wird. - 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_typeundexc_tracebackdessys-Moduls [1] zugunsten vonsys.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
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-3110.rst
Zuletzt geändert: 2025-02-01 08:59:27 GMT