⚙️
중급 (Intermediate)
try/except/else/finally · raise · 사용자 정의 예외
5주차 — 예외 처리
try/except의 4개 절(try·except·else·finally), 여러 예외 분기 처리, raise로 의도적 발생, Exception 상속으로 사용자 정의 예외, 예외 체인을 익힙니다.
exceptiontryraisecustom
소요 시간
⏱ 2시간
난이도
📊 중급
선수 조건
🎯 4주차
결과물
안전하게 회복 가능한 입력·파일·네트워크 처리
이 강의에서 배우는 것
- 1try/except/else/finally 의 각 절을 안다
- 2예외 종류를 구분해 처리한다
- 3사용자 정의 예외를 만든다
- 4예외를 의도적으로 발생시킨다(raise)
1. 예외란
실행 중 발생하는 오류. 처리하지 않으면 프로그램이 종료됨.
python
print(10 / 0) # ZeroDivisionError
print(int("abc")) # ValueError
print([1,2][5]) # IndexError2. try / except
python
try:
n = int(input("숫자: "))
print(10 / n)
except ValueError:
print("숫자가 아닙니다")
except ZeroDivisionError:
print("0으로 나눌 수 없습니다")
except Exception as e:
print(f"기타 에러: {e}")3. else / finally
- else: try가 예외 없이 끝났을 때
- finally: 예외 여부와 무관하게 항상 실행 (정리 작업)
python
try:
f = open("data.txt")
except FileNotFoundError:
print("파일 없음")
else:
print(f.read())
f.close()
finally:
print("정리 완료")4. raise
예외를 의도적으로 발생.
python
def withdraw(balance, amount):
if amount > balance:
raise ValueError("잔액 부족")
return balance - amount5. 사용자 정의 예외
Exception 상속.
python
class InsufficientFundsError(Exception):
pass
def transfer(account, amount):
if account.balance < amount:
raise InsufficientFundsError(f"잔액 {account.balance} < 요청 {amount}")6. 예외 체인
기존 예외를 감싸서 새 예외 발생.
python
try:
int("abc")
except ValueError as e:
raise RuntimeError("입력 처리 실패") from e7. 자주 하는 실수
- 너무 광범위한 except (except: pass) — 위험. 가능한 좁은 예외 클래스 명시
- except ... as e: pass — 에러를 숨김. 최소한 로그라도
- finally 에서 return — try의 return 값을 덮어쓸 수 있음
- except 순서 — 좁은 예외(FileNotFoundError) 먼저, 넓은 것(OSError) 뒤에
8. FAQ
Q1. 모든 함수에 try를 둘러싸야 하나요?
아닙니다. 회복할 수 있는 곳에서만. 보통 사용자 입력, 파일 I/O, 네트워크 호출.
Q2. Exception 과 BaseException 의 차이?
BaseException 이 최상위. KeyboardInterrupt, SystemExit 도 포함. 일반적으로는 Exception 까지만 잡음.
Q3. 예외 vs 반환값 (None / -1)?
예외는 "정상 흐름이 아님" 을 명확히. 검색에서 "없음" 같은 정상 상황은 None 권장.
💻 예제 (examples)
실제로 실행해 결과를 확인할 수 있는 예제 코드입니다.
01_try_except.py— 기본 try/except + 여러 예외
CODE
try:
n = int(input("숫자: "))
print(10 / n)
except ValueError:
print("숫자가 아닙니다")
except ZeroDivisionError:
print("0으로 나눌 수 없습니다")
except Exception as e:
print(f"기타 에러: {e}")
▶ 실행 결과
숫자: abc
숫자가 아닙니다
숫자: 0
0으로 나눌 수 없습니다
숫자: 5
2.002_else_finally.py— else, finally
CODE
try:
f = open("hello.txt", encoding="utf-8")
except FileNotFoundError:
print("파일 없음")
else:
print(f.read())
f.close()
finally:
print("정리 완료")
▶ 실행 결과
# 파일 있을 때
Hello, World!
정리 완료
# 파일 없을 때
파일 없음
정리 완료03_raise.py— raise + 입력 검증
CODE
def withdraw(balance, amount):
if amount <= 0:
raise ValueError("금액은 양수여야 합니다")
if amount > balance:
raise ValueError("잔액 부족")
return balance - amount
try:
print(withdraw(1000, 500))
print(withdraw(500, 1000))
except ValueError as e:
print("에러:", e)
▶ 실행 결과
500
에러: 잔액 부족04_custom.py— 사용자 정의 예외
CODE
class InsufficientFundsError(Exception):
pass
class Account:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
if amount > self.balance:
raise InsufficientFundsError(
f"잔액 {self.balance} < 요청 {amount}"
)
self.balance -= amount
try:
a = Account(1000)
a.withdraw(2000)
except InsufficientFundsError as e:
print("거래 거부:", e)
▶ 실행 결과
거래 거부: 잔액 1000 < 요청 2000📝 과제 (exercises)
직접 풀어보고, 막힐 때 정답을 펼쳐 비교해보세요.
과제 1
안전한 정수 입력 (read_int)
목표: 잘못된 입력이면 다시 받는 read_int(prompt) 함수.
요구사항
- ValueError 잡아서 다시 입력 받기
- while True 로 정상 입력될 때까지 반복
입출력 예시
숫자: abc
숫자가 아닙니다. 다시 입력하세요.
숫자: 1.5
숫자가 아닙니다. 다시 입력하세요.
숫자: 42
입력값: 42▶정답 코드 펼치기 / 접기
SOLUTION
def read_int(prompt):
while True:
try:
return int(input(prompt))
except ValueError:
print("숫자가 아닙니다. 다시 입력하세요.")
n = read_int("숫자: ")
print(f"입력값: {n}")
▶ 실행 결과
숫자: abc
숫자가 아닙니다. 다시 입력하세요.
숫자: 42
입력값: 42과제 2
사용자 정의 예외 InvalidScoreError
목표: 0~100 범위가 아닌 점수면 InvalidScoreError.
요구사항
- InvalidScoreError(Exception) 정의
- validate_score(s) 함수 — 잘못되면 raise
- 테스트로 try/except 처리
입출력 예시
유효: 85
거부: 점수는 0~100 사이여야 합니다 (입력: 150)▶정답 코드 펼치기 / 접기
SOLUTION
class InvalidScoreError(Exception):
pass
def validate_score(s):
if not (0 <= s <= 100):
raise InvalidScoreError(f"점수는 0~100 사이여야 합니다 (입력: {s})")
return s
for v in [85, 150]:
try:
validate_score(v)
print(f"유효: {v}")
except InvalidScoreError as e:
print(f"거부: {e}")
▶ 실행 결과
유효: 85
거부: 점수는 0~100 사이여야 합니다 (입력: 150)과제 3
파일 읽기 예외 처리
목표: 파일이 없으면 친절한 메시지, 인코딩 오류면 다른 메시지.
요구사항
- FileNotFoundError → "파일 없음"
- UnicodeDecodeError → "인코딩 오류"
- 정상 — 첫 5줄만 출력
입출력 예시
파일 없음: data.txt▶정답 코드 펼치기 / 접기
SOLUTION
def show_first_lines(path, n=5):
try:
with open(path, encoding="utf-8") as f:
for i, line in enumerate(f):
if i >= n:
break
print(line.rstrip())
except FileNotFoundError:
print(f"파일 없음: {path}")
except UnicodeDecodeError:
print(f"인코딩 오류: {path} (UTF-8 아님)")
show_first_lines("data.txt")
▶ 실행 결과
파일 없음: data.txt