예외가 발생할 수 있는 코드를 try 블록에 작성하고, 오류 발생 시 처리할 코드를 except에 작성
else/finally 사용
예외가 발생하지 않았을 때의 처리(else)나, 무조건 실행되는 코드(finally) 작성
raise 문
사용자가 직접 오류를 발생시킬 수 있는 구문 (강제 오류 발생 시 사용)
2) 이론 설명
1. 예외(Exception) 처리란?
예외(Exception)는 프로그램 실행 중 오류가 발생하는 모든 상황을 의미합니다.
예외 처리는 이러한 오류 상황에서도 프로그램을 강제 종료하지 않고, 정상 흐름을 유지할 수 있도록 처리하는 방식입니다.
네트워크 장비 상태 수집이나 로그 분석 자동화 프로그램에서도 연결 실패, 포맷 오류 등의 예외를 처리하지 않으면 전체 자동화가 중단되므로, 반드시 필요한 개념입니다.
Python에서는 try, except, else, finally, raise 문을 통해 예외 처리 흐름을 세밀하게 제어할 수 있습니다.
프로그램 실행 도중 발생할 수 있는 오류를 예측하고, 해당 오류를 안전하게 처리하는 방식입니다.
예외 처리를 하지 않으면 오류 발생 시 프로그램이 강제 종료됩니다.
예외 처리는 try ~ except 문을 중심으로 다양한 방식으로 사용할 수 있습니다.
2. 주요 예외 종류
Python에서 자주 발생하는 예외는 어떤 코드 상황에서 발생하는지 명확히 이해해야 문제를 빠르게 해결할 수 있습니다.
예외 유형
발생 조건 및 설명
SyntaxError
잘못된 문법(예: 괄호, 콜론 누락 등) 사용 시 발생. 프로그램 실행 전에 발생함.
IndentationError
들여쓰기가 잘못되었을 때 발생. Python은 들여쓰기를 통해 블록을 구분하기 때문에 중요.
NameError
존재하지 않는 변수나 객체에 접근했을 때 발생. 오타나 선언 누락 등으로 자주 발생함.
TypeError
잘못된 타입 간 연산 또는 호출 시 발생. 예: 문자열 + 정수 연산, 함수 호출 대상이 아닌 객체 호출 등
ValueError
자료형은 맞지만 값이 적절하지 않을 때 발생. 예: int("abc"), 리스트에서 없는 값을 remove() 할 때 등
ZeroDivisionError
숫자를 0으로 나누려 할 때 발생. 나눗셈, 나머지 연산에서 해당.
FileNotFoundError
open() 등으로 파일을 열 때, 해당 파일이 존재하지 않을 경우 발생.
IndexError
시퀀스 자료형(리스트 등)에서 존재하지 않는 인덱스를 참조할 때 발생.
KeyError
딕셔너리에 존재하지 않는 키를 참조할 때 발생. dict['없는키'] 사용 시 발생함.
3. try-except 기본 구조
try 블록에 예외가 발생할 수 있는 코드를 작성하고,
except 블록에서 해당 예외를 잡아 처리합니다.
as 키워드를 통해 예외 메시지를 변수로 받아올 수 있습니다.
기본적인 예외 처리는 아래와 같은 구조를 따릅니다:
try:
실행할 코드
except 예외종류 as 변수:
예외 발생 시 처리할 코드
예제 1: ZeroDivisionError 처리
숫자를 0으로 나누려고 하면 ZeroDivisionError가 발생합니다.
이를 사전에 처리하여 프로그램이 멈추지 않도록 할 수 있습니다.
num = int(input("숫자를 입력하세요: "))
try:
print(100 / num)
except ZeroDivisionError as e:
print("0으로는 나눌 수 없습니다.", e)
try:
result = 10 / 0
except ZeroDivisionError as e:
print("예외 발생:", e)
예제 2: try ~ else
else 블록은 예외가 발생하지 않았을 때만 실행됩니다.
예외 없이 정상적으로 실행되었음을 구분하고자 할 때 사용합니다.
port = input("포트 번호를 입력하세요: ")
try:
port_num = int(port)
except ValueError:
print("숫자만 입력 가능합니다.")
else:
print(f"{port_num}번 포트가 입력되었습니다.")
try:
result = 10 / 2
except ZeroDivisionError as e:
print("오류 발생:", e)
else:
print("정상 처리 결과:", result)
예제 3: try ~ finally
finally 블록은 예외 발생 여부와 관계없이 항상 실행되는 영역입니다.
예를 들어, 파일을 열고 나서 무조건 닫아야 할 경우, 또는 네트워크 세션 종료 등 자원 해제를 위한 블록입니다.
try:
f = open("config.txt", "r")
print(f.read())
except FileNotFoundError:
print("파일이 존재하지 않습니다.")
finally:
print("파일 읽기 시도 완료")
try:
result = 10 / 0
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
finally:
print("ZeroDivisionError 확인 완료")
예제 4: 예외 무시하기 (pass 사용)
예외가 발생했을 때 아무 조치도 하지 않고 그냥 넘어가야 할 경우 pass를 사용할 수 있습니다.
하지만 중요한 예외까지 무시하면 문제가 발생할 수 있으므로 주의해서 사용합니다.
user_input = input("숫자 입력: ")
try:
print(int(user_input))
except ValueError:
pass # 형식 오류 무시하고 넘어감
print("프로그램 계속 진행 중...")
try:
10 / 0
except ZeroDivisionError:
pass # 아무런 처리 없이 넘어감
예제 5: 예외 강제로 발생시키기 (raise)
raise 문을 사용하면 사용자가 직접 예외를 발생시킬 수 있습니다.
유효성 검사에서 조건이 맞지 않을 때 명확한 에러 메시지를 주고 종료하기 위해 많이 사용합니다.
device_name = ""
try:
if not device_name:
raise ValueError("장비 이름이 비어 있습니다.")
except ValueError as e:
print("오류 발생:", e)
try:
raise NameError("사용자 정의 NameError")
except NameError as e:
print("직접 발생시킨 오류:", e)
3) 종합 실습
과제 1: 사용자 입력 오류 처리기 작성
문제 설명 : 사용자로부터 숫자 2개를 입력받아 나눗셈을 수행하는 프로그램을 작성하세요.
두 입력값 중 하나라도 숫자가 아닌 경우 ValueError를 처리합니다.
나눗셈 시 0으로 나누는 경우는 ZeroDivisionError로 처리합니다.
예외가 없을 경우 정상 결과를 출력하며, 마지막에는 항상 "프로그램 종료"를 출력하도록 finally 블록을 사용합니다.
과제 2: 장비 딕셔너리 키 접근 오류 처리
문제 설명 : 장비 상태를 담은 딕셔너리에서 사용자 입력에 따라 장비 상태를 출력하세요.
존재하지 않는 장비 이름을 입력하면 KeyError로 처리하여 안내 메시지를 출력합니다.
과제 3: 포트 번호 검사기 (raise 사용)
문제 설명 : 사용자에게 포트 번호를 입력받고 유효한 범위(1~65535)인지 검사합니다.
범위를 벗어난 경우 raise ValueError로 명시적인 오류를 발생시키고 메시지를 출력하세요.