파이썬 try except 예외 처리 — 에러를 다루는 정석
파이썬 try except 예외 처리란?
파이썬 try except 예외 처리는 프로그램 실행 중 발생하는 오류(예외)를 잡아 프로그램이 중단되지 않게 다루는 방법입니다. 예를 들어 0으로 나누거나, 없는 파일을 열거나, 숫자가 아닌 입력을 정수로 바꾸려 할 때 예외가 발생합니다. 이런 상황을 미리 처리해 두면 안정적인 프로그램을 만들 수 있습니다.
기본 문법
try:
result = 10 / 0
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
# 출력: 0으로 나눌 수 없습니다.
try 블록 안에서 예외가 발생하면, 해당 예외에 맞는 except 블록이 실행됩니다. 예외가 없으면 except는 건너뜁니다.
예외 메시지 받기
as 키워드로 예외 객체를 받아 메시지를 확인할 수 있습니다.
try:
int("abc")
except ValueError as e:
print(f"변환 실패: {e}")
# 변환 실패: invalid literal for int() with base 10: 'abc'
여러 예외 처리
예외 종류별로 다르게 처리하려면 except를 여러 개 둡니다. 여러 예외를 한꺼번에 잡으려면 괄호로 묶습니다.
try:
value = int(input())
result = 100 / value
except ValueError:
print("숫자를 입력하세요.")
except ZeroDivisionError:
print("0은 안 됩니다.")
except (TypeError, KeyError) as e:
print(f"기타 오류: {e}")
else와 finally
else는 예외가 없을 때만 실행되고, finally는 예외 발생 여부와 관계없이 항상 실행됩니다. 파일을 닫는 등 정리 작업에 유용합니다.
try:
num = int("42")
except ValueError:
print("실패")
else:
print(f"성공: {num}") # 성공: 42
finally:
print("항상 실행됩니다.")
실전 예제
직접 예외 발생시키기 (raise)
def set_age(age):
if age < 0:
raise ValueError("나이는 음수가 될 수 없습니다.")
return age
try:
set_age(-5)
except ValueError as e:
print(e) # 나이는 음수가 될 수 없습니다.
파일 처리 시 안전하게
try:
with open("data.txt", "r", encoding="utf-8") as f:
content = f.read()
except FileNotFoundError:
print("파일이 없습니다.")
except PermissionError:
print("읽기 권한이 없습니다.")
with 문을 쓰면 예외가 나도 파일이 자동으로 닫히므로 finally로 직접 닫을 필요가 없습니다.
자주 하는 실수
- 그냥 except: 만 쓰기: 모든 예외를 무차별로 잡으면 진짜 버그까지 숨겨집니다. 가능한 한 구체적인 예외(
ValueError등)를 지정하세요. - 예외를 조용히 무시:
except: pass는 문제 원인을 가려 디버깅을 어렵게 만듭니다. 최소한 로그라도 남기세요. - try 범위를 너무 넓게: 한 줄만 위험한데 수십 줄을 try로 감싸면 어디서 오류가 났는지 알기 어렵습니다. 위험한 코드만 감싸세요.
- 흐름 제어용으로 남용: 단순 조건 확인은
if로 충분합니다. 예외는 "예외적 상황"에 쓰는 것이 원칙입니다.
try 구문 키워드 정리
| 키워드 | 실행 시점 |
|---|---|
| try | 예외가 발생할 수 있는 코드 |
| except | 지정한 예외가 발생했을 때 |
| else | 예외가 발생하지 않았을 때 |
| finally | 예외 여부와 무관하게 항상 |
자주 묻는 질문
Q. except의 순서가 중요한가요?
네. 구체적인 예외를 먼저, 포괄적인 예외(Exception 등)를 나중에 둬야 합니다. 포괄 예외를 먼저 두면 그 아래 구체적 except가 실행될 기회가 없습니다.
Q. except Exception과 except:는 같나요?
거의 같지만 미묘하게 다릅니다. except Exception은 일반 예외만 잡고, 맨 except는 KeyboardInterrupt 같은 시스템 종료 신호까지 잡아버립니다. 보통은 except Exception이 더 안전합니다.
Q. 예외를 잡은 뒤 다시 위로 전달하려면요?
except 블록 안에서 인자 없이 raise만 쓰면 잡았던 예외를 그대로 다시 던집니다. 로그를 남기고 상위로 전파할 때 자주 쓰는 패턴입니다.