C'est une position de continuation de l'article suivant
Regardez l'arborescence des exceptions intégrées dans Python
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)
C'est essentiellement la même chose que la dernière fois, mais nous avons supprimé toutes les anciennes protections Python 3 et Python 2 du support. De plus, j'ai utilisé des guillemets doubles récemment parce que le noir le fait.
Utilisez «3.7.7» comme cible de comparaison. Dans l'article précédent, le dernier était «3.7.1», mais il n'y avait aucune différence dans l'arborescence des exceptions, donc je l'ai omis.
L'environnement disponible est MacOS 10.15.4, mais il ne devrait y avoir aucune différence dans la couche Python.
La méthode d'exécution est à peu près la suivante
$ 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
(Le même contenu que ci-dessus est enregistré dans le texte)
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
Puisqu'il s'agit d'une source de comparaison, je ne ferai pas de commentaire en particulier. Il ne semblait y avoir aucune différence dans les résultats de 3.7.1.
$ 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
C'est assez différent. C'est la même chose que la version 3.8-dev la dernière fois, et je crains qu'elle ne "diminue" unilatéralement, mais je pense que cela est dû à l'implémentation de ce script.
J'ai remarqué quand j'ai regardé Quoi de neuf, mais je n'ai pas pu saisir toutes les exceptions en premier lieu, ce script. Pas de bon enfant!
asyncio.CancelledError
Ce n'est pas le résultat en premier lieu.
Je ne fais que maintenir un article bâclé, donc je ne vais pas creuser plus profondément, mais vous ne devriez pas penser que c'est exhaustif, Maru.
Comme je l'ai toujours ressenti, je pense qu'il vaut mieux contester cette branche d'arbre d'exception en supposant qu'elle changera en tant que sentiment personnel.
Tout d'abord, en tant que savoir-faire de développement, c'est fondamentalement un endroit où vous dérivez votre propre exception de ʻException et assurez-vous que l'exception que votre code émet explicitement est clairement séparée de l'exception d'exécution par ʻexcept
. Taisez-vous. Si vous avez besoin, par exemple, de regarder les classes d'exceptions avec un grain plus fin que ʻOSError`, c'est comme écrire un test unitaire, en reconnaissant la possibilité qu'il change d'une version à l'autre. Si vous écrivez un test qui détecte les exceptions dans le test unitaire, même si l'arborescence de l'exception change lorsque vous modifiez le runtime, le test unitaire le remarquera immédiatement, vous vous sentirez donc plus en sécurité.
En premier lieu, en partant du principe que la théorie de la POO est que les parents ne devraient pas avoir toutes les classes pour enfants dès le début.
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.
C'est une erreur fondamentale que j'ai faite. Je n'ai pas remarqué depuis des années (^^;
Réécrivons le script comme suit
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)
Prenez un diff
$ diff 377.txt 382.txt
1c1
< Python Version: 3.7.7
---
> Python Version: 3.8.2
Pas de changement.
Il semble donc exact que 3.8.2 n'a pas au moins réduit le nombre d'exceptions, et qu'elles n'ont pas été importées inutilement au démarrage du runtime.
Bien sûr, lorsque vous importez explicitement, ces exceptions sont chargées au moment de l'exécution et peuvent maintenant être trouvées dans la classe parente __subclasses__ ()
.
C'est une simple amélioration.
Recommended Posts