한양과학기술고등학교

에듀테크 프로젝트 대시보드

예외 처리

try except finally raise with

파이썬은 "허락보다 용서"(EAFP) — 미리 검사하기보다 일단 시도하고 예외를 잡습니다.

1. try / except

try:
    n = int(input("숫자: "))
    result = 10 / n
except ValueError:
    print("숫자가 아님")
except ZeroDivisionError:
    print("0으로 나눔")
except (KeyError, IndexError) as e:      # 여러 개 묶기 + 객체 받기
    print(f"조회 실패: {e}")
except Exception as e:                    # 최후 방어 (너무 광범위 주의)
    print(f"예상 못한 오류: {e!r}")

2. else / finally

try:
    f = open("data.txt")
except FileNotFoundError:
    print("파일 없음")
else:
    data = f.read()       # try 가 예외 없이 끝났을 때만
finally:
    f.close()             # 예외 여부와 무관하게 항상 실행 (정리 작업)

3. raise

def withdraw(balance, amount):
    if amount > balance:
        raise ValueError(f"잔액 부족: {balance} < {amount}")
    return balance - amount

# 예외를 잡아 로깅 후 다시 던지기
try:
    risky()
except Exception:
    log.exception("실패")
    raise                 # 원래 예외 그대로 전파

# 원인 연결
raise RuntimeError("처리 실패") from original_error

4. 사용자 정의 예외

class AppError(Exception):
    """앱 기본 예외"""

class NotFoundError(AppError):
    def __init__(self, resource):
        super().__init__(f"{resource}를 찾을 수 없음")
        self.resource = resource

try:
    raise NotFoundError("사용자")
except AppError as e:      # 부모로 잡으면 하위 전부 포함
    print(e)

5. with — 컨텍스트 매니저

# 파일·락·연결 등 자원을 자동으로 정리
with open("data.txt", encoding="utf-8") as f:
    data = f.read()
# 블록을 벗어나면 예외가 나도 f.close() 보장

with open("a") as fa, open("b", "w") as fb:   # 여러 개
    fb.write(fa.read())

import threading
lock = threading.Lock()
with lock:
    shared_state += 1

6. EAFP vs LBYL

# LBYL (Look Before You Leap) — 경쟁 조건에 취약
if key in d:
    value = d[key]

# EAFP (Easier to Ask Forgiveness) — 파이썬다운 방식
try:
    value = d[key]
except KeyError:
    value = default
# 더 간단: d.get(key, default)
예외 처리 원칙
  • except: (모두 잡기) 금지 — KeyboardInterrupt 까지 삼킴. except Exception:
  • 잡은 예외를 조용히 pass 하지 말 것 (최소한 로깅)
  • try 블록은 예외가 날 만한 코드만 좁게
"명시적인 것이 암시적인 것보다 낫다 (Explicit is better than implicit)"