Take a look at the built-in exception tree structure in Python 3.8.2

It is a continuation position of the following article

Look at the Python built-in exception tree structure

Scripts to use, environment, usage examples

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)

It's essentially the same as last time, but we've removed all old Python 3 protection and Python 2 support. Also, I've been using double quotes recently because black does so.

Use 3.7.7 as the comparison target. In the previous article, the last one was 3.7.1, but there was no difference in the exception tree, so I omitted it.

My environment is MacOS 10.15.4, but there should be no difference in the Python layer.

The execution method is roughly as follows

$ 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
(The same content as above is saved in the text)

Execution result in 3.7.7 (full text)

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

Since this is a comparison source, I will not comment in particular. There did not seem to be any difference in the results from 3.7.1.

Execution result in 3.8.2 (comparison)

$ 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

It's quite different. It's the same as 3.8-dev last time, and I'm worried that it is unilaterally "decreasing", but I think this is due to the implementation of this script.

I noticed when I looked at What's New, but I couldn't catch all the exceptions in the first place, this script. No good child!

asyncio.CancelledError

This is not the result in the first place.

I'm just maintaining a sloppy article, so I won't dig deeper, but you shouldn't think it's exhaustive, Maru.

But I'm wondering why I couldn't catch it. If you know it (No, I can guess a little)

As I have always felt, I think it is better to challenge this exception tree branch on the assumption that it will change as a personal feeling.

First of all, as a development know-how, it is basically a place where you derive your own exception from ʻException and make the exception explicitly issued by your code clearly separated from the runtime exception by ʻexcept. Keep it down. If you need to, for example, look at the exception class with a finer particle size than ʻOSError`, it's like writing a unit test, recognizing the possibility that it will change from version to version. If you write a test that catches exceptions in a unit test, even if the tree structure of the exception changes when you change the runtime, the unit test will immediately notice it, so you will feel more secure.

I investigated while saying

In the first place, on the premise that the theory of OOP is that parents should not have all the child classes from the beginning.

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.

This is a basic mistake I've made. I haven't noticed for years (^^;

Let's rewrite the script as follows

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)

Take a diff

$ diff 377.txt 382.txt
1c1
< Python Version: 3.7.7
---
> Python Version: 3.8.2

No change.

So it seems correct that 3.8.2 didn't at least reduce the number of exceptions, and that they weren't imported unnecessarily when the runtime was started.

Of course, when I explicitly imported, those exceptions were loaded at runtime and could be found in the parent class __subclasses__ ().

This is a simple improvement.

Recommended Posts

Take a look at the built-in exception tree structure in Python 3.8.2
Take a look at the Python built-in exception tree structure
Take a screenshot in Python
I took a quick look at the fractions package that handles Python built-in fractions.
Let's take a look at the Scapy code. How are you processing the structure?
[Go] Take a look at io.Writer
Take a look at Django's template.
Let's take a look at the feature map of YOLO v3
Output tree structure of files in Python
Run the Python interpreter in a script
Draw a tree in Python 3 using graphviz
[Python] Get the files in a folder with Python
Get the caller of a function in Python
Make a copy of the list in Python
Output in the form of a python array
[Python] Find the transposed matrix in a comprehension
Let's look at a differential equation that cannot be solved normally in Python
Turn multiple lists with a for statement at the same time in Python
System trade starting with Python3: Bio-health stocks to look at in the new Corona
Check if the string is a number in python
[Python] Take a screenshot
Take a peek at the processing of LightGBM Tuner
Drawing a tree structure with D3.js in Jupyter Notebook
C-like structure in Python
Write a log-scale histogram on the x-axis in python
A reminder about the implementation of recommendations in Python
Take a look at profiling and dumping with Dataflow
Don't take an instance of a Python exception class directly as an argument to the exception class!
What does the last () in a function mean in Python?
Challenge image classification by TensorFlow2 + Keras 2 ~ Let's take a closer look at the input data ~
Find out the apparent width of a string in python
Try using the Python web framework Django (2) --Look at setting.py
Create a local scope in Python without polluting the namespace
How to use the __call__ method in a Python class
Change the standard output destination to a file in Python
A quick look at your profile within the django app
Get the number of specific elements in a python list
[Note] Import of a file in the parent directory in Python
How to get the last (last) value in a list in Python
How to get a list of built-in exceptions in python
Create a function in Python
Create a dictionary in Python
Download the file in Python
Find the difference in Python
Make a bookmarklet in Python
Let's take a look at the infection tendency of the new coronavirus COVID-19 in each country and the medical response status (additional information).
Hannari Python At the LT meeting in December, I made a presentation on "Python and Bayesian statistics".
When learning a programming language, it's a good idea to first look at the family tree of the programming language.
Play a sound in Python assuming that the keyboard is a piano keyboard
How to determine the existence of a selenium element in Python
How to know the internal structure of an object in Python
How to check the memory size of a variable in Python
Delete a particular character in Python if it is the last
Read the standard output of a subprocess line by line in Python
A function that measures the processing time of a method in python
I took a closer look at why Python self is needed
Read a file in Python with a relative path from the program
Get the formula in an excel file as a string in Python
Solve the subset sum problem with a full search in Python
Get the number of readers of a treatise on Mendeley in Python
Let's take a look at the forest fire on the west coast of the United States with satellite images.