파이썬 예외 처리 — try·except·finally
에러가 나도 프로그램이 죽지 않게. 입문 단계 마지막 도구.
사용자에게 나이를 묻고 int() 로 변환하는 코드. 사용자가 "서른" 이라고 입력하면 ValueError 가 빨갛게 뜨고 프로그램이 죽습니다. 파일을 여는데 파일이 없으면 FileNotFoundError, 0 으로 나누면 ZeroDivisionError. 현실 프로그램은 에러가 예외가 아니라 일상이에요. 사용자 입력·파일·네트워크가 끼면 거의 항상 뭔가 어긋납니다.
12편을 마치면 ① try/except 기본 ② 에러 종류로 분기 ③ else·finally ④ raise 로 직접 발생 ⑤ "함정 — 광범위 except 의 위험" — 5가지로 견고한 프로그램을 짜는 토대.
try·except 기본 구조
# 위험: 잘못된 입력에 죽음
age = int(input("나이: ")) # "서른" 입력 → ValueError → 프로그램 종료
# 안전: try 로 감싸기
try:
age = int(input("나이: "))
print(f"내년 {age + 1}살")
except ValueError:
print("숫자를 입력해주세요")
try 블록 안에서 에러가 나면 즉시 except 로 점프해 처리. 에러가 안 나면 except 는 그냥 건너뜁니다. 두 블록 모두 들여쓰기 4칸으로 묶여요.
중요한 두 가지. ① try 안에서 에러가 난 줄 이후는 실행 안 됩니다. 위에서 int 가 실패하면 print 도 안 나가요. ② except 블록을 지나면 프로그램은 다음 코드로 정상 진행. 에러가 처리됐기 때문.
에러 종류로 분기 — 여러 except
에러는 종류가 매우 많고(파이썬에 약 70개 내장 예외), 각기 다른 처리가 필요합니다.
try:
with open("config.json") as f:
data = json.load(f)
age = int(data["age"])
except FileNotFoundError:
print("config.json 이 없습니다 — 기본값으로 시작")
except KeyError:
print("config 에 'age' 키가 없습니다")
except (ValueError, TypeError): # 튜플로 묶어 여러 종류 한꺼번에
print("age 값이 숫자가 아닙니다")
각 except 는 가장 가까운 매치만 잡습니다. FileNotFoundError 가 나면 첫 except 만 실행되고 나머지는 안 거쳐요.
📌 자주 만나는 예외 7종
· ValueError — 자료형은 맞는데 값이 이상 (int("abc"))
· TypeError — 자료형 충돌 ("a" + 1)
· KeyError — dict 에 없는 키
· IndexError — list 범위 밖 인덱스
· FileNotFoundError — 파일이 없음
· ZeroDivisionError — 0 으로 나눔
· KeyboardInterrupt — 사용자 Ctrl+C
else·finally — 흐름 마무리 2 도구
try:
f = open("data.txt")
text = f.read()
except FileNotFoundError:
print("파일 없음")
else:
print(f"읽은 길이: {len(text)}") # 예외 안 났을 때만 실행
finally:
if 'f' in dir():
f.close() # 무조건 실행 — 정리·해제
- else — try 가 예외 없이 끝났을 때만 실행. "실패하면 건너뛰고, 성공하면 후속 처리" 의도를 명확하게 표현. 정상 흐름과 예외 처리를 시각적으로 분리.
- finally — 예외가 났든 안 났든 항상 실행. 파일 닫기·DB 연결 해제·리소스 정리 같은 마무리 작업. 함수가 도중에
return해도 finally 는 실행됩니다.
실무 권장 — with 문이 더 짧음
# 파일 닫기는 with 가 try-finally 보다 간결
with open("data.txt") as f:
text = f.read()
# 블록 끝나면 자동 close — finally 불필요
# 묶어서
try:
with open("data.txt") as f:
text = f.read()
except FileNotFoundError:
text = ""
13편에서 with 패턴을 정식으로 다룹니다.
raise·광범위 except 의 함정
raise — 직접 예외 일으키기
def divide(a, b):
if b == 0:
raise ValueError("0 으로 나눌 수 없습니다")
return a / b
try:
divide(10, 0)
except ValueError as e:
print(f"에러: {e}") # 에러: 0 으로 나눌 수 없습니다
as e 로 예외 객체를 받아 메시지를 꺼낼 수 있어요. 함수가 잘못된 인자를 받았을 때 명시적 에러를 일으켜 호출자에게 알리는 패턴 — 입문자가 코드 품질을 한 단계 올리는 도구입니다.
except: 또는 except Exception: pass 는 모든 에러를 잡아 묻어버립니다. 버그가 일어나도 조용히 진행돼서 1주 뒤에 "왜 잘못된 데이터가 쌓였지" 추적 지옥. 무엇을 처리할지 정확히 알 때 그 종류만 잡으세요.
# ❌ 절대 금지
try:
risky()
except:
pass # 모든 에러 묵살
# ❌ 좀 낫지만 여전히 위험
try:
risky()
except Exception:
pass # KeyboardInterrupt 만 제외하고 다 묵살
# ✅ 명시적으로
try:
risky()
except (ValueError, TypeError) as e:
log.warning(f"입력 문제: {e}")
# 의도적 처리 또는 폴백
마무리 — 예외는 흐름의 일부
입문자는 예외를 "에러" 라고만 생각하지만, 파이썬은 예외를 제어 흐름의 도구로도 씁니다. 사용자가 Ctrl+C 를 누르면 KeyboardInterrupt, 반복문에서 더 이상 값이 없으면 StopIteration. "실패할 수 있다" 는 사실을 인정하고 정중하게 처리하는 코드가 실무 파이썬의 절반입니다.
다음 미션 — REPL 에서: ① 입력받은 두 숫자로 나눗셈, 0 또는 비숫자에 안전 ② 파일 읽기 함수에서 없으면 빈 문자열 반환 ③ 본인의 validate_age(age) 함수 — 1~120 외면 ValueError raise.
다음 편 미리보기
13편 — "파이썬 파일 읽기·쓰기": open·with·read·write 패턴과 CSV·JSON 같이 자주 만나는 형식 처리.
← 11편 "모듈 import" · 다음: 13편 "파일 읽기·쓰기"