例外の階層構造

Pythonでは、すべての例外はBaseExceptionクラスから派生しています。つまり、Pythonの例外はすべてBaseExceptionまたはそのサブクラスのインスタンスです。
BaseExceptionクラスは例外階層の最上位のクラスであり、__str____repr__など、すべての例外が使用できる共通のメソッドを提供します。しかし、BaseExceptionを直接コードで使用するべきではありません。なぜなら、それは範囲が広すぎて、あらゆる種類の例外を捕捉してしまうからです。代わりに、BaseExceptionのサブクラスであるより具体的な例外クラスを使用するべきです。Pythonは多くの組み込み例外クラスを提供しており、自分自身でカスタムの例外クラスを作成することもできます:
BaseException
 ├── BaseExceptionGroup
 ├── GeneratorExit
 ├── KeyboardInterrupt
 ├── SystemExit
 └── Exception
      ├── ArithmeticError
      │    ├── FloatingPointError
      │    ├── OverflowError
      │    └── ZeroDivisionError
      ├── AssertionError
      ├── AttributeError
      ├── BufferError
      ├── EOFError
      ├── ExceptionGroup [BaseExceptionGroup]
      ├── ImportError
      │    └── ModuleNotFoundError
      ├── LookupError
      │    ├── IndexError
      │    └── KeyError
      ├── MemoryError
      ├── NameError
      │    └── UnboundLocalError
      ├── OSError
      │    ├── BlockingIOError
      │    ├── ChildProcessError
      │    ├── ConnectionError
      │    │    ├── BrokenPipeError
      │    │    ├── ConnectionAbortedError
      │    │    ├── ConnectionRefusedError
      │    │    └── ConnectionResetError
      │    ├── FileExistsError
      │    ├── FileNotFoundError
      │    ├── InterruptedError
      │    ├── IsADirectoryError
      │    ├── NotADirectoryError
      │    ├── PermissionError
      │    ├── ProcessLookupError
      │    └── TimeoutError
      ├── ReferenceError
      ├── RuntimeError
      │    ├── NotImplementedError
      │    └── RecursionError
      ├── StopAsyncIteration
      ├── StopIteration
      ├── SyntaxError
      │    └── IndentationError
      │         └── TabError
      ├── SystemError
      ├── TypeError
      ├── ValueError
      │    └── UnicodeError
      │         ├── UnicodeDecodeError
      │         ├── UnicodeEncodeError
      │         └── UnicodeTranslateError
      └── Warning
           ├── BytesWarning
           ├── DeprecationWarning
           ├── EncodingWarning
           ├── FutureWarning
           ├── ImportWarning
           ├── PendingDeprecationWarning
           ├── ResourceWarning
           ├── RuntimeWarning
           ├── SyntaxWarning
           ├── UnicodeWarning
           └── UserWarning
The hierarchy of built-in exception classes in Python (from the official Python docs).
つまり、FileNotFoundErrorOSErrorのサブクラスであり、OSErrorExceptionクラスのサブクラスで、そのExceptionクラス自体がBaseExceptionから継承されています。

例外の階層構造を尊重する

複数のexcept文を使用する際には、Pythonの例外階層構造を尊重することが重要です。つまり、Exceptionのような基底の例外クラスを捕捉する場合、より具体的な例外をその前に捕捉する必要があります。もし基底クラスの後により具体的なクラスのexcept文を書いても、そのブロックは実行されません:
try:
    # 例外を発生させる可能性のあるコード
except ValueError:
    # ValueErrorを処理する
except Exception:
    # その他の例外を処理する
この例では、ValueError例外が最初に捕捉されます。コードが他のExceptionから派生した例外を発生させた場合、2つ目のexceptブロックのコードが実行されます。しかし、Exceptionを直接捕捉することはおすすめできません。これは範囲が広すぎて、あらゆる種類の例外を捕捉してしまうからです。可能な限り、より具体的な例外を捕捉する方がよいでしょう:
try:
    ...
except TypeError:
    ...
except ValueError:
    ...
except Exception:
    ...
tryブロック内のコードがTypeErrorValueErrorを発生させた場合、それぞれ対応するexceptブロックが実行されます。コードが他のExceptionから派生した例外を発生させた場合、3つ目のexceptブロックのコードが実行されます。
もし基底の例外を最初のexceptブロックに置くと、残りのブロックは決して実行されません:
try:
    # 例外を発生させる可能性のあるコード
except Exception as e:               # これはすべてのエラーを捕捉します
    print(f'An error occurred: {e}')
except ValueError:                   # これは実行されません
    print('A ValueError occurred')
except TypeError:                    # これは実行されません
    print('A TypeError occurred')
この例では、tryブロックは任意の種類の例外を発生させる可能性があります。しかし、最初のexcept文が基底のExceptionクラスを捕捉しているため、発生したすべての例外を捕捉します。エラーメッセージが表示され、残りのexcept文は実行されません。

チャレンジ:ファイルを解析する

あなたは大量のデータを扱うスタートアップでソフトウェアエンジニアとして働いています。最近、チームはデータの保存と処理にJSONファイルを使用することを決定しました。このデータはあなたのスタートアップの運営にとって非常に重要であり、これらのJSONファイルを読み込み解析するPythonプログラムを作成するのがあなたの仕事です。
しかし、大量のデータと複数の人が関わっているため、いくつかのエラーが頻繁に発生します:
  1. データファイルが存在しない場合があります。
  1. データファイルが空の場合があります。
  1. データファイルに有効なJSONでないデータが含まれている場合があります。
あなたのPythonプログラムは、これらの例外をクラッシュせずに処理し、データチームが迅速に問題を特定し修正できるよう、意味のあるエラーメッセージを提供する必要があります。
あなたのプログラムは、ファイル名を表す文字列を入力として受け取り、次のケースに対応する必要があります:
  • ファイルが存在しない場合、FileNotFoundErrorを発生させ、適切なエラーメッセージを表示します。
  • ファイルが空の場合、ValueErrorを発生させ、適切なエラーメッセージを表示します。
  • ファイルの内容が有効なJSONでない場合、json.JSONDecodeErrorValueErrorのサブクラス)を発生させ、適切なエラーメッセージを表示します。この例外を発生させる際には、docposの属性をパラメータとして提供する必要があります。
💡
except json.JSONDecodeError as e:
これらの例外はそれぞれ独立して処理されるべきであり、あなたのプログラムは各ケースに対して具体的なエラーメッセージを提供する必要があります。
入力
出力
nonexistent_file.json
FileNotFoundError: File 'nonexistent_file.json' does not exist.
empty_file.json
ValueError: File 'empty_file.json' is empty.
invalid_json.json
JSONDecodeError: Content of file 'invalid_json.json' is not valid JSON.: line 1 column 1 (char 0)
success.json
File 'success.json' has been successfully parsed as valid JSON.
 

Constraints

Time limit: 2 seconds

Memory limit: 512 MB

Output limit: 1 MB

To check your solution you need to sign in
Sign in to continue