← 파이썬 강의 목록으로
⚙️
중급 (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])       # IndexError

2. 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 - amount

5. 사용자 정의 예외

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 e

7. 자주 하는 실수

  1. 너무 광범위한 except (except: pass) — 위험. 가능한 좁은 예외 클래스 명시
  2. except ... as e: pass — 에러를 숨김. 최소한 로그라도
  3. finally 에서 return — try의 return 값을 덮어쓸 수 있음
  4. 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.0
02_else_finally.pyelse, 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.pyraise + 입력 검증
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
예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗