Es ist eine Fortsetzung des folgenden Artikels
Sehen Sie sich die Baumstruktur der in Python integrierten Ausnahmen an
class_tree.py
#!/usr/bin/env python
import platform
def show_class_tree(cls, depth=0):
prefix = "" if depth == 0 else "." * (depth * 3) + " "
if cls.__name__.lower() == "error":
print("{}{} ({})".format(prefix, cls.__name__, cls))
else:
print("{}{}".format(prefix, cls.__name__))
for subcls in sorted(cls.__subclasses__(), key=lambda c: c.__name__):
show_class_tree(subcls, depth+1)
if __name__ == "__main__":
print("Python Version: {}".format(platform.python_version()))
print()
show_class_tree(BaseException)
Es ist im Wesentlichen dasselbe wie beim letzten Mal, aber wir haben alle alten Python 3-Schutzfunktionen und Python 2 aus der Unterstützung entfernt. Außerdem habe ich in letzter Zeit doppelte Anführungszeichen verwendet, weil Schwarz dies tut.
Verwenden Sie 3.7.7
als Vergleichsziel. Im vorherigen Artikel war der letzte "3.7.1", aber es gab keinen Unterschied im Ausnahmebaum, also habe ich ihn weggelassen.
Die vorliegende Umgebung ist MacOS 10.15.4, aber es sollte keinen Unterschied in der Python-Ebene geben.
Die Ausführungsmethode ist ungefähr wie folgt
$ python -V
Python 3.7.7
$ python class_tree.py | tee $(python -c 'import platform; print("".join(platform.python_version_tuple()) + ".txt")')
Python Version: 3.7.7
...
$ cat 377.txt
(Der gleiche Inhalt wie oben wird im Text gespeichert)
Python Version: 3.7.7
BaseException
... Exception
...... ArithmeticError
......... FloatingPointError
......... OverflowError
......... ZeroDivisionError
...... AssertionError
...... AttributeError
...... BufferError
...... EOFError
...... Error (<class 'locale.Error'>)
...... ImportError
......... ModuleNotFoundError
......... ZipImportError
...... LookupError
......... CodecRegistryError
......... IndexError
......... KeyError
...... MemoryError
...... NameError
......... UnboundLocalError
...... OSError
......... BlockingIOError
......... ChildProcessError
......... ConnectionError
............ BrokenPipeError
............ ConnectionAbortedError
............ ConnectionRefusedError
............ ConnectionResetError
......... FileExistsError
......... FileNotFoundError
......... InterruptedError
......... IsADirectoryError
......... ItimerError
......... NotADirectoryError
......... PermissionError
......... ProcessLookupError
......... TimeoutError
......... UnsupportedOperation
...... ReferenceError
...... RuntimeError
......... BrokenBarrierError
......... NotImplementedError
......... RecursionError
......... _DeadlockError
...... StopAsyncIteration
...... StopIteration
...... StopTokenizing
...... SubprocessError
......... CalledProcessError
......... TimeoutExpired
...... SyntaxError
......... IndentationError
............ TabError
...... SystemError
......... CodecRegistryError
...... TokenError
...... TypeError
...... ValueError
......... UnicodeError
............ UnicodeDecodeError
............ UnicodeEncodeError
............ UnicodeTranslateError
......... UnsupportedOperation
...... Verbose
...... Warning
......... BytesWarning
......... DeprecationWarning
......... FutureWarning
......... ImportWarning
......... PendingDeprecationWarning
......... ResourceWarning
......... RuntimeWarning
......... SyntaxWarning
......... UnicodeWarning
......... UserWarning
...... _OptionError
...... error (<class 're.error'>)
... GeneratorExit
... KeyboardInterrupt
... SystemExit
Da dies eine Vergleichsquelle ist, werde ich nicht besonders darauf eingehen. Es schien keinen Unterschied in den Ergebnissen von 3.7.1 zu geben.
$ diff 377.txt 382.txt
1c1
< Python Version: 3.7.7
---
> Python Version: 3.8.2
44d43
< ......... BrokenBarrierError
50,53d48
< ...... StopTokenizing
< ...... SubprocessError
< ......... CalledProcessError
< ......... TimeoutExpired
59d53
< ...... TokenError
79d72
< ...... _OptionError
Es ist ganz anders. Es ist das gleiche wie beim letzten Mal mit 3.8-dev und ich mache mir Sorgen, dass es einseitig "abnimmt", aber ich denke, das liegt an der Implementierung dieses Skripts.
Ich habe es bemerkt, als ich mir Was ist neu angeschaut habe, aber ich konnte überhaupt nicht alle Ausnahmen erfassen, dieses Skript. Kein gutes Kind!
asyncio.CancelledError
Dies ist nicht in erster Linie das Ergebnis.
Ich pflege nur einen schlampigen Artikel, damit ich nicht tiefer grabe, aber du solltest nicht denken, dass er erschöpfend ist, Maru.
Wie ich immer gefühlt habe, denke ich, dass es besser ist, diesen Ausnahmebaumzweig unter der Annahme herauszufordern, dass er sich als persönliches Gefühl ändern wird.
Zunächst sollten Sie als Entwicklungs-Know-how als Grundregel Ihre eigene Ausnahme von "Ausnahme" ableiten und sicherstellen, dass Ausnahmen, die explizit von Ihrem Code ausgegeben werden, durch "Ausnahme" klar von Laufzeitausnahmen getrennt sind. Halte es unten. Wenn Sie beispielsweise die Ausnahmeklassen mit einer feineren Körnung als "OSError" betrachten müssen, ist dies wie das Schreiben eines Komponententests, bei dem die Möglichkeit erkannt wird, dass er sich von Version zu Version ändert. Wenn Sie einen Test schreiben, der Ausnahmen im Komponententest abfängt, bemerkt der Komponententest dies sofort, auch wenn sich die Baumstruktur der Ausnahme ändert, wenn Sie die Laufzeit ändern, sodass Sie sich sicherer fühlen.
Erstens unter der Voraussetzung, dass die Theorie der OOP lautet, dass Eltern nicht von Anfang an alle Kinderklassen haben sollten.
https://stackoverflow.com/questions/3862310/how-to-find-all-the-subclasses-of-a-class-given-its-name
Note that if the class definition of a subclass hasn't been executed yet - for example, if the subclass's module hasn't been imported yet - then that subclass doesn't exist yet, and subclasses won't find it.
Dies ist ein grundlegender Fehler, den ich gemacht habe. Ich habe es seit Jahren nicht mehr bemerkt (^^;
Schreiben wir das Skript wie folgt um
class_tree_mod.py
#!/usr/bin/env python
import platform
from threading import BrokenBarrierError
from tokenize import StopTokenizing
from warnings import _OptionError
from subprocess import SubprocessError
def show_class_tree(cls, depth=0):
prefix = "" if depth == 0 else "." * (depth * 3) + " "
if cls.__name__.lower() == "error":
print("{}{} ({})".format(prefix, cls.__name__, cls))
else:
print("{}{}".format(prefix, cls.__name__))
for subcls in sorted(cls.__subclasses__(), key=lambda c: c.__name__):
show_class_tree(subcls, depth+1)
if __name__ == "__main__":
print("Python Version: {}".format(platform.python_version()))
print()
show_class_tree(BaseException)
Nehmen Sie einen Diff
$ diff 377.txt 382.txt
1c1
< Python Version: 3.7.7
---
> Python Version: 3.8.2
Keine Änderung.
Es scheint also richtig zu sein, dass 3.8.2 die Anzahl der Ausnahmen nicht mindestens verringert hat und dass sie zu Beginn der Laufzeit nicht unnötig importiert wurden.
Wenn Sie explizit importieren, werden diese Ausnahmen natürlich zur Laufzeit geladen und befinden sich jetzt in der übergeordneten Klasse __subclasses__ ()
.
Dies ist eine einfache Verbesserung.
Recommended Posts