본문 바로가기
코딩취미/Python

파이썬 예외처리(try, except, else, finally) 방법 과 사용자 정의 예외 처리 객체 사용

by 브링블링 2024. 6. 1.
728x90

파이썬 예외처리 방법과 사용자 정의 예외 처리 객체 사용

예외 처리(Exception Handling)는 프로그램에서 발생할 수 있는 오류나 예외 상황을 처리하는 방법입니다. 이를 통해 프로그램의 예기치 않은 종료를 방지하고, 사용자에게 적절한 피드백을 제공할 수 있습니다. 파이썬에서는 try, except, else, finally 블록을 사용하여 예외 처리를 수행합니다.

A. 예외 처리의 구성 요소 (요약)

  1. try 블록: 예외가 발생할 가능성이 있는 코드를 포함합니다.
  2. except 블록: 특정 예외가 발생했을 때 실행되는 코드를 포함합니다. 여러 개의 except 블록을 사용할 수 있으며, 각 블록은 다른 예외 유형을 처리할 수 있습니다.
  3. else 블록: 예외가 발생하지 않았을 때 실행되는 코드를 포함합니다. 이 블록은 선택적입니다.
  4. finally 블록: 예외 발생 여부와 관계없이 항상 실행되는 코드를 포함합니다. 주로 자원 해제나 정리 작업에 사용됩니다.

B. 주요 예외 클래스

  • Exception: 모든 내장 예외의 기본 클래스입니다.
  • ArithmeticError: 수치 연산 예외의 기본 클래스입니다.
  • ZeroDivisionError: 0으로 나누기 예외입니다.
  • OverflowError: 수치 연산의 결과가 너무 커서 표현할 수 없는 경우 발생합니다.
  • LookupError: 시퀀스 인덱스나 키가 잘못된 경우 발생합니다.
  • IndexError: 시퀀스 인덱스가 범위를 벗어난 경우 발생합니다.
  • KeyError: 딕셔너리 키가 존재하지 않는 경우 발생합니다.
  • ValueError: 연산이나 함수가 인수 유형은 올바르지만 부적절한 값을 받았을 때 발생합니다.
  • TypeError: 연산이나 함수가 인수가 잘못된 유형일 때 발생합니다.
  • IOError: 입출력 연산 실패 시 발생합니다.
  • FileNotFoundError: 파일이 존재하지 않을 때 발생합니다.

기본 예외 처리 구문

try:
    # 예외가 발생할 가능성이 있는 코드
    result = 10 / 0
except ZeroDivisionError:
    # ZeroDivisionError 예외가 발생했을 때 실행되는 코드
    print("Cannot divide by zero!")
else:
    # 예외가 발생하지 않았을 때 실행되는 코드
    print("Division was successful!")
finally:
    # 예외 발생 여부와 관계없이 항상 실행되는 코드
    print("Execution finished.")

 

1) 여러 예외 처리

하나의 try 블록에서 여러 예외를 처리할 수 있습니다. 각 예외 유형에 대해 별도의 except 블록을 사용합니다.

try:
    value = int(input("Enter a number: "))
    result = 10 / value
except ZeroDivisionError:
    print("Cannot divide by zero!")
except ValueError:
    print("Invalid input! Please enter a valid number.")
except Exception as e:
    print(f"An unexpected error occurred: {e}")
else:
    print(f"The result is {result}")
finally:
    print("Execution finished.")

 

2) 예외 객체

예외 객체는 발생한 예외에 대한 정보를 포함합니다. 이를 통해 예외 메시지나 기타 속성을 확인할 수 있습니다.

try:
    value = int(input("Enter a number: "))
    result = 10 / value
except Exception as e:
    print(f"An error occurred: {e}")
    print(f"Exception type: {type(e)}")

 

3) 사용자 정의 예외

사용자 정의 예외를 만들어 특정 상황에 대해 고유한 예외를 처리할 수 있습니다. 사용자 정의 예외는 Exception 클래스를 상속받아 정의합니다.

class MyCustomError(Exception):
    def __init__(self, message):
        self.message = message
        super().__init__(self.message)

try:
    raise MyCustomError("This is a custom error message")
except MyCustomError as e:
    print(f"A custom error occurred: {e}")

 

4) 예외 체인

파이썬에서는 예외를 다시 발생시켜 예외 체인을 만들 수 있습니다. 이때 raise 키워드 뒤에 원래 예외를 포함할 수 있습니다.

try:
    try:
        value = int(input("Enter a number: "))
        result = 10 / value
    except ZeroDivisionError as e:
        raise MyCustomError("Division by zero in inner block") from e
except MyCustomError as e:
    print(f"A custom error occurred: {e}")
    print(f"Original exception: {e.__cause__}")
728x90

C. 사용자 정의 예외 클래스 정의 방법 (상세)

사용자 정의 예외를 사용하면 특정 상황에 맞는 예외를 만들고 처리할 수 있어 코드의 가독성과 유지보수성을 높일 수 있습니다. 사용자 정의 예외 클래스를 정의하려면 기본적으로 Exception 클래스를 상속받아 정의합니다. 이 클래스는 일반 예외 클래스와 동일하게 작동하지만, 사용자 정의 메시지나 추가 속성을 포함할 수 있습니다.

  • 기본 사용자 정의 예외: Exception 클래스를 상속받아 간단히 정의합니다.
  • 추가 속성 포함: 예외 클래스에 추가적인 속성을 포함하여 더 많은 정보를 제공할 수 있습니다.
  • 예외 체인: 사용자 정의 예외를 사용하여 다른 예외를 래핑할 수 있습니다.
  • 계층 구조: 여러 예외를 계층 구조로 정의하여 다양한 오류 상황을 세분화할 수 있습니다.

기본 사용자 정의 예외

class MyCustomError(Exception):
    def __init__(self, message):
        super().__init__(message)

 

1) 간단한 사용자 정의 예외

class NegativeNumberError(Exception):
    """Raised when the input value is negative."""
    def __init__(self, value):
        self.value = value
        self.message = f"Negative numbers are not allowed: {value}"
        super().__init__(self.message)

def check_positive(number):
    if number < 0:
        raise NegativeNumberError(number)
    else:
        return f"The number is positive: {number}"

try:
    result = check_positive(-10)
except NegativeNumberError as e:
    print(e)
else:
    print(result)

 

2) 추가 속성을 이용한 사용자 정의 예외

class InvalidAgeError(Exception):
    """Raised when the input age is invalid."""
    def __init__(self, age, message="Age must be between 0 and 120"):
        self.age = age
        self.message = message
        super().__init__(self.message)

def check_age(age):
    if age < 0 or age > 120:
        raise InvalidAgeError(age)
    else:
        return f"Valid age: {age}"

try:
    result = check_age(150)
except InvalidAgeError as e:
    print(f"Invalid age error: {e.age} - {e.message}")
else:
    print(result)

 

3) 사용자 정의 예외 체인

사용자 정의 예외를 사용하여 다른 예외를 래핑(wrapping)할 수 있습니다. 이를 통해 예외 체인을 만들고 원래 예외를 참조할 수 있습니다.

class DatabaseError(Exception):
    """Base class for database errors."""
    pass

class ConnectionError(DatabaseError):
    """Raised when a connection to the database fails."""
    def __init__(self, original_exception):
        super().__init__(f"Failed to connect to database: {original_exception}")
        self.original_exception = original_exception

def connect_to_database():
    try:
        raise ValueError("Original connection error")
    except ValueError as e:
        raise ConnectionError(e)

try:
    connect_to_database()
except ConnectionError as e:
    print(e)
    print(f"Original exception: {e.original_exception}")

 

4) 사용자 정의 예외 계층 구조

여러 사용자 정의 예외를 계층 구조로 정의하여 다양한 오류 상황을 세분화할 수 있습니다.

class ApplicationError(Exception):
    """Base class for application errors."""
    pass

class FileProcessingError(ApplicationError):
    """Raised when an error occurs during file processing."""
    pass

class DataValidationError(ApplicationError):
    """Raised when data validation fails."""
    pass

def process_file(file_path):
    if not file_path.endswith('.txt'):
        raise FileProcessingError(f"Invalid file type: {file_path}")
    # File processing logic here
    return "File processed successfully"

def validate_data(data):
    if not isinstance(data, dict):
        raise DataValidationError(f"Invalid data format: {data}")
    # Data validation logic here
    return "Data validated successfully"

try:
    file_result = process_file("data.csv")
    print(file_result)
except FileProcessingError as e:
    print(e)

try:
    data_result = validate_data(["not", "a", "dict"])
    print(data_result)
except DataValidationError as e:
    print(e)

 

 

728x90