파이썬 예외처리 방법과 사용자 정의 예외 처리 객체 사용
예외 처리(Exception Handling)는 프로그램에서 발생할 수 있는 오류나 예외 상황을 처리하는 방법입니다. 이를 통해 프로그램의 예기치 않은 종료를 방지하고, 사용자에게 적절한 피드백을 제공할 수 있습니다. 파이썬에서는 try, except, else, finally 블록을 사용하여 예외 처리를 수행합니다.
A. 예외 처리의 구성 요소 (요약)
- try 블록: 예외가 발생할 가능성이 있는 코드를 포함합니다.
- except 블록: 특정 예외가 발생했을 때 실행되는 코드를 포함합니다. 여러 개의 except 블록을 사용할 수 있으며, 각 블록은 다른 예외 유형을 처리할 수 있습니다.
- else 블록: 예외가 발생하지 않았을 때 실행되는 코드를 포함합니다. 이 블록은 선택적입니다.
- 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__}")
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)
'코딩취미 > Python' 카테고리의 다른 글
전체 파일경로에서 파일명과 폴더경로를 분리하는 방법 : os , pathlib 사용 (0) | 2024.06.12 |
---|---|
QLineEdit 안에 Button 넣는 방법 : QToolButton or QAction 사용 (0) | 2024.06.11 |
코드 재사용 및 최적화를 위해 사용하는 functools 주요 기능 6가지 (partial, lru_cache, cmp_to_key, reduce, total_ordering, wraps) (0) | 2024.05.31 |
partial 사용 방법과 이벤트 핸들러 적용 시 장점 (0) | 2024.05.30 |
딕셔너리 값을 보기 좋게 출력하는 방법 (pprint, json) (0) | 2024.05.27 |