Python 에서 특정 예외 유형 확인하는 방법

PythonBeginner
지금 연습하기

소개

이 랩에서는 효과적인 오류 처리에 필수적인 기술인, Python 에서 예외가 특정 유형인지 확인하는 방법을 배우게 됩니다. 이 랩은 예외 계층 구조를 이해하고 이 지식을 활용하여 특정 예외 유형을 식별하는 데 중점을 둡니다.

이 랩은 BaseException 기본 클래스와 Exception과 같은 하위 클래스부터 시작하여 Python 예외 계층 구조를 탐구하도록 안내합니다. Python 스크립트 exception_hierarchy.py를 생성하여 예외 계층 구조를 출력함으로써 다양한 예외 클래스 간의 관계를 시각화할 수 있습니다. 그런 다음, isinstance() 및 직접적인 클래스 비교를 사용하여 예외 유형을 확인하는 후속 단계에서 이 이해를 적용하게 됩니다.

예외 계층 구조 이해

이 단계에서는 Python 의 예외 계층 구조에 대해 배우게 됩니다. 이 계층 구조를 이해하는 것은 효과적인 오류 처리에 매우 중요합니다. Python 의 예외는 트리 구조로 구성되어 있으며, 맨 위에 기본 클래스가 있고, 더 구체적인 예외 클래스가 이를 상속받습니다.

모든 예외의 기본 클래스는 BaseException입니다. BaseException에서 직접 상속되는 클래스는 Exception, GeneratorExit, KeyboardInterrupt, 그리고 SystemExit입니다. Exception 클래스는 프로그램에서 발생할 수 있는 오류를 나타내는 대부분의 내장 예외의 슈퍼클래스입니다.

이 계층 구조를 탐구하기 위해 Python 스크립트를 만들어 보겠습니다.

  1. VS Code 편집기를 엽니다.

  2. ~/project 디렉토리에 exception_hierarchy.py라는 새 파일을 생성합니다.

    ~/project/exception_hierarchy.py
    
  3. exception_hierarchy.py 파일에 다음 코드를 추가합니다.

    def print_exception_hierarchy(exception_class, indent=0):
        """Prints the exception hierarchy starting from a given exception class."""
        print('  ' * indent + str(exception_class))
        for subclass in exception_class.__subclasses__():
            print_exception_hierarchy(subclass, indent + 1)
    
    print("Exception Hierarchy:")
    print_exception_hierarchy(Exception)
    

    이 스크립트는 Exception 클래스부터 시작하여 예외 계층 구조를 출력하는 재귀 함수 print_exception_hierarchy를 정의합니다.

  4. 터미널에서 다음 명령을 사용하여 스크립트를 실행합니다.

    python exception_hierarchy.py
    

    이렇게 하면 예외 계층 구조의 트리 구조가 터미널에 출력됩니다.

    예시 출력:

    Exception Hierarchy:
    <class 'Exception'>
      <class 'ArithmeticError'>
        <class 'FloatingPointError'>
        <class 'OverflowError'>
        <class 'ZeroDivisionError'>
          <class 'decimal.DivisionByZero'>
      <class 'AssertionError'>
      <class 'AttributeError'>
      <class 'BufferError'>
      <class 'EOFError'>
      <class 'ImportError'>
        <class 'ModuleNotFoundError'>
        <class 'ZipImportError'>
      <class 'LookupError'>
        <class 'IndexError'>
        <class 'KeyError'>
          <class 'tracemalloc.DomainKey'>
      <class 'MemoryError'>
      <class 'NameError'>
        <class 'UnboundLocalError'>
      <class 'OSError'>
        <class 'BlockingIOError'>
        <class 'ChildProcessError'>
        <class 'ConnectionError'>
          <class 'BrokenPipeError'>
          <class 'ConnectionAbortedError'>
          <class 'ConnectionRefusedError'>
          <class 'ConnectionResetError'>
        <class 'FileExistsError'>
        <class 'FileNotFoundError'>
        <class 'InterruptedError'>
          <class 'InterruptedSystemCall'>
        <class 'IsADirectoryError'>
        <class 'NotADirectoryError'>
        <class 'PermissionError'>
        <class 'ProcessLookupError'>
        <class 'TimeoutError'>
        <class 'UnsupportedOperation'>
        <class 'itertools.Incomplete'>
        <class 'signal.ItimerError'>
      <class 'ReferenceError'>
      <class 'RuntimeError'>
        <class 'NotImplementedError'>
          <class 'asyncio.exceptions.IncompleteReadError'>
          <class 'zlib.error'>
        <class '_frozen_importlib._DeadlockError'>
        <class 'RecursionError'>
      <class 'StopAsyncIteration'>
      <class 'StopIteration'>
      <class 'SyntaxError'>
        <class 'IndentationError'>
          <class 'TabError'>
      <class 'SystemError'>
      <class 'TypeError'>
      <class 'ValueError'>
        <class 'UnicodeError'>
          <class 'UnicodeDecodeError'>
          <class 'UnicodeEncodeError'>
          <class 'UnicodeTranslateError'>
      <class 'Warning'>
        <class 'BytesWarning'>
        <class 'DeprecationWarning'>
        <class 'EncodingWarning'>
        <class 'FutureWarning'>
        <class 'ImportWarning'>
        <class 'PendingDeprecationWarning'>
        <class 'ResourceWarning'>
        <class 'RuntimeWarning'>
        <class 'SyntaxWarning'>
        <class 'UnicodeWarning'>
        <class 'UserWarning'>
    

    이 출력은 Exception을 기본 클래스로 하고 다양한 하위 클래스가 특정 유형의 오류를 나타내는 예외의 계층 구조를 보여줍니다. 이 계층 구조를 이해하면 적절한 세분성 수준에서 예외를 잡는 데 도움이 됩니다. 예를 들어, ZeroDivisionError와 같은 특정 예외 또는 ArithmeticError ( ZeroDivisionError의 상위 클래스) 와 같은 더 일반적인 예외를 잡을 수 있습니다.

예외에 isinstance() 사용

이 단계에서는 isinstance() 함수를 사용하여 예외가 특정 클래스 또는 클래스 튜플의 인스턴스인지 확인하는 방법을 배우게 됩니다. 이는 다양한 유형의 예외를 유연하게 처리하는 데 유용합니다.

isinstance() 함수는 두 개의 인수를 받습니다: 객체와 classinfo. 객체가 classinfo 의 인스턴스이거나 하위 클래스의 인스턴스인 경우 True를 반환합니다. 그렇지 않으면 False를 반환합니다.

예외와 함께 isinstance() 사용법을 시연하기 위해 Python 스크립트를 만들어 보겠습니다.

  1. VS Code 편집기를 엽니다.

  2. ~/project 디렉토리에 isinstance_exception.py라는 새 파일을 생성합니다.

    ~/project/isinstance_exception.py
    
  3. isinstance_exception.py 파일에 다음 코드를 추가합니다.

    try:
        result = 10 / 0
    except Exception as e:
        if isinstance(e, ZeroDivisionError):
            print("Caught a ZeroDivisionError!")
        elif isinstance(e, ArithmeticError):
            print("Caught an ArithmeticError!")
        else:
            print("Caught some other exception!")
    
    print("Program continues...")
    

    이 스크립트에서는 10 을 0 으로 나누려고 시도하며, 이는 ZeroDivisionError를 발생시킵니다. 그런 다음 예외를 잡고 isinstance()를 사용하여 ZeroDivisionError 또는 ArithmeticError의 인스턴스인지 확인합니다.

  4. 터미널에서 다음 명령을 사용하여 스크립트를 실행합니다.

    python isinstance_exception.py
    

    이렇게 하면 "Caught a ZeroDivisionError!"가 터미널에 출력됩니다.

    예시 출력:

    Caught a ZeroDivisionError!
    Program continues...
    

    출력은 isinstance() 함수가 예외를 ZeroDivisionError의 인스턴스로 올바르게 식별했음을 보여줍니다. ZeroDivisionErrorArithmeticError의 하위 클래스이므로 첫 번째 if 조건이 충족되고 해당 메시지가 출력됩니다.

    이제 더 일반적인 예외를 잡도록 스크립트를 수정해 보겠습니다.

  5. isinstance_exception.py 파일을 다음과 같이 수정합니다.

    try:
        result = int("abc")
    except Exception as e:
        if isinstance(e, ZeroDivisionError):
            print("Caught a ZeroDivisionError!")
        elif isinstance(e, ValueError):
            print("Caught a ValueError!")
        elif isinstance(e, ArithmeticError):
            print("Caught an ArithmeticError!")
        else:
            print("Caught some other exception!")
    
    print("Program continues...")
    

    이 수정된 스크립트에서는 문자열 "abc"를 정수로 변환하려고 시도하며, 이는 ValueError를 발생시킵니다.

  6. 동일한 명령을 사용하여 스크립트를 다시 실행합니다.

    python isinstance_exception.py
    

    이렇게 하면 "Caught a ValueError!"가 터미널에 출력됩니다.

    예시 출력:

    Caught a ValueError!
    Program continues...
    

    이 출력은 isinstance()를 사용하여 서로 다른 유형의 예외를 구별하고 그에 따라 처리할 수 있음을 보여줍니다.

예외 클래스로 확인

이 단계에서는 except 블록에서 특정 예외 클래스를 직접 확인하는 방법을 배우게 됩니다. 이는 isinstance()를 사용하는 것보다 더 직접적이고 종종 더 명확한 예외 처리 방법입니다.

except ExceptionType as e:를 사용하면 ExceptionType 유형 또는 해당 하위 클래스인 예외만 잡도록 Python 에 지시하는 것입니다.

이를 시연하기 위해 Python 스크립트를 만들어 보겠습니다.

  1. VS Code 편집기를 엽니다.

  2. ~/project 디렉토리에 exception_classes.py라는 새 파일을 생성합니다.

    ~/project/exception_classes.py
    
  3. exception_classes.py 파일에 다음 코드를 추가합니다.

    try:
        result = 10 / 0
    except ZeroDivisionError as e:
        print("Caught a ZeroDivisionError:", e)
    except ArithmeticError as e:
        print("Caught an ArithmeticError:", e)
    except Exception as e:
        print("Caught some other exception:", e)
    
    print("Program continues...")
    

    이 스크립트에서는 10 을 0 으로 나누려고 시도하며, 이는 ZeroDivisionError를 발생시킵니다. ZeroDivisionError, ArithmeticError, 그리고 Exception에 대한 세 개의 except 블록이 있습니다.

  4. 터미널에서 다음 명령을 사용하여 스크립트를 실행합니다.

    python exception_classes.py
    

    이렇게 하면 "Caught a ZeroDivisionError: division by zero"가 터미널에 출력됩니다.

    예시 출력:

    Caught a ZeroDivisionError: division by zero
    Program continues...
    

    출력은 ZeroDivisionError가 첫 번째 except 블록에 의해 잡혔음을 보여줍니다.

    이제 다른 예외를 발생시키도록 스크립트를 수정해 보겠습니다.

  5. exception_classes.py 파일을 다음과 같이 수정합니다.

    try:
        result = int("abc")
    except ZeroDivisionError as e:
        print("Caught a ZeroDivisionError:", e)
    except ValueError as e:
        print("Caught a ValueError:", e)
    except ArithmeticError as e:
        print("Caught an ArithmeticError:", e)
    except Exception as e:
        print("Caught some other exception:", e)
    
    print("Program continues...")
    

    이 수정된 스크립트에서는 문자열 "abc"를 정수로 변환하려고 시도하며, 이는 ValueError를 발생시킵니다.

  6. 동일한 명령을 사용하여 스크립트를 다시 실행합니다.

    python exception_classes.py
    

    이렇게 하면 "Caught a ValueError: invalid literal for int() with base 10: 'abc'"가 터미널에 출력됩니다.

    예시 출력:

    Caught a ValueError: invalid literal for int() with base 10: 'abc'
    Program continues...
    

    이 출력은 ValueError가 두 번째 except 블록에 의해 잡혔음을 보여줍니다.

    except 블록에서 예외 클래스를 직접 지정함으로써, 명확하고 체계적인 방식으로 다양한 유형의 예외를 처리할 수 있습니다. 이 접근 방식은 간단한 예외 처리를 위해 isinstance()를 사용하는 것보다 일반적으로 선호됩니다.

요약

이 랩에서는 효과적인 오류 처리에 중요한 Python 의 예외 계층 구조를 탐구했습니다. 예외가 BaseException을 기본 클래스로, 대부분의 내장 예외에 대한 Exception을 슈퍼클래스로 하는 트리 구조로 구성되어 있음을 배웠습니다.

Exception 클래스부터 시작하여 예외 계층 구조를 출력하는 Python 스크립트 exception_hierarchy.py를 만들었습니다. 스크립트를 실행하여 예외의 트리 구조와 관계를 관찰함으로써 Python 에서 예외가 어떻게 구성되는지에 대한 더 나은 이해를 얻었습니다.