예외 처리
프로그램 실행 중 발생하는 에러를 우아하게 처리하는 방법让我们学习. 예외 처리는 안정적인 프로그램을 만드는 핵심입니다.
예외란? 🤔
예외(Exception)는 프로그램 실행 중 발생하는 오류입니다.
# 예외가 발생하는 코드
result = 10 / 0 # ZeroDivisionError
ZeroDivisionError: division by zero
기본 예외 처리: try-except
단순 예외 처리
try:
result = 10 / 0
except:
print('에러가 발생했습니다')
특정 예외 처리
try:
number = int(input('숫자를 입력하세요: '))
result = 10 / number
except ZeroDivisionError:
print('0으로 나눌 수 없습니다')
except ValueError:
print('올바른 숫자를 입력하세요')
예외 메시지 받기
try:
file = open('없는파일.txt', 'r')
except FileNotFoundError as e:
print(f'파일을 찾을 수 없습니다: {e}')
try-except-else-finally
전체 구조
try:
# 실행할 코드
result = 10 / 2
except ZeroDivisionError:
# 예외 발생 시 실행
print('0으로 나눌 수 없습니다')
else:
# 예외가 없을 때만 실행
print(f'결과: {result}')
finally:
# 항상 실행 (예외 발생 여부와 무관)
print('계산 완료')
实践示例: 파일 처리
def read_file(filename):
file = None
try:
file = open(filename, 'r', encoding='utf-8')
content = file.read()
return content
except FileNotFoundError:
print(f'파일이 없습니다: {filename}')
return None
except PermissionError:
print(f'读取文件 권한이 없습니다: {filename}')
return None
finally:
if file:
file.close()
print('파일을 닫았습니다')
# 사용 예제
content = read_file('data.txt')
주요 예외 종류 📋
일반적인 예외
# ZeroDivisionError: 0으로 나누기
try:
10 / 0
except ZeroDivisionError:
print('0으로 나눌 수 없습니다')
# ValueError: 잘못된 값
try:
int('abc')
except ValueError:
print('숫자로 변환할 수 없습니다')
# TypeError: 잘못된 타입
try:
'문자열' + 123
except TypeError:
print('타입이 맞지 않습니다')
# IndexError: 잘못된 인덱스
try:
my_list = [1, 2, 3]
print(my_list[10])
except IndexError:
print('인덱스가 범 위를 벗어났습니다')
# KeyError: 없는 키
try:
my_dict = {'a': 1}
print(my_dict['b'])
except KeyError:
print('키가 존재하지 않습니다')
# AttributeError: 없는 속성
try:
my_str = 'hello'
my_str.append('!')
except AttributeError:
print('해당 속성이 없습니다')
파일 관련 예외
# FileNotFoundError: 파일 없음
try:
open('없는파일.txt', 'r')
except FileNotFoundError:
print('파일을 찾을 수 없습니다')
# PermissionError: 권한 없음
try:
open('/root/file.txt', 'r')
except PermissionError:
print('파일 접근 권한이 없습니다')
# IsADirectoryError: 디렉토리를 파일로 열기
try:
open('some_directory', 'r')
except IsADirectoryError:
print('디렉토리입니다')
여러 예외를 한 번에 처리하기
튜플로 묶기
try:
# 어떤 작업
result = risky_operation()
except (ValueError, TypeError, KeyError):
print('값, 타입 또는 키 에러가 발생했습니다')
각각 다르게 처리하기
try:
data = fetch_data()
value = int(data)
except ValueError as e:
print(f'값 변환 에러: {e}')
except ConnectionError as e:
print(f'연결 에러: {e}')
except Exception as e: # 모든 예외 처리
print(f'알 수 없는 에러: {e}')
예외 발생시키기 (raise) 🚀
기본 raise
def divide(a, b):
if b == 0:
raise ValueError('b는 0이 될 수 없습니다')
return a / b
try:
result = divide(10, 0)
except ValueError as e:
print(e) # 'b는 0이 될 수 없습니다'
예외 재발생
def process_data(data):
try:
result = complex_operation(data)
except ValueError as e:
print(f'데이터 처리 중 에러 발생: {e}')
raise # 예외를 다시 발생시킴
try:
process_data(invalid_data)
except ValueError:
print('상위 레벨에서 처리')
예외 체인
def load_config():
try:
with open('config.txt', 'r') as f:
return f.read()
except FileNotFoundError as e:
raise RuntimeError('설정 파일을 로드할 수 없습니다') from e
try:
config = load_config()
except RuntimeError as e:
print(e)
print(f'원인: {e.__cause__}')
커스텀 예외 만들기 🎨
기본 커스텀 예외
class InvalidAgeError(Exception):
"""나이가 유효하지 않을 때 발생하는 예외"""
pass
def set_age(age):
if age < 0 or age > 150:
raise InvalidAgeError(f'유효하지 않은 나이: {age}')
return age
try:
set_age(-5)
except InvalidAgeError as e:
print(e)
메시지와 데이터를 포함하는 예외
class ValidationError(Exception):
"""데이터 검증 실패 예외"""
def __init__(self, field, value, message):
self.field = field
self.value = value
self.message = message
super().__init__(f'{field}: {message} (값: {value})')
def validate_user(user):
if not user.get('email'):
raise ValidationError('email', user.get('email'), '이메일은 필수입니다')
if len(user.get('name', '')) < 2:
raise ValidationError('name', user.get('name'), '이름은 2자 이상이어야 합니다')
try:
validate_user({'name': 'A'})
except ValidationError as e:
print(f'필드: {e.field}')
print(f'