프로그램 실행 중 발생하는 오류(Error)를 if 조건문으로 일일이 막으려 하면 코드가 매우 난잡해집니다. 파이썬에서는 '코드 수행 블록'과 '예외 처리 블록'을 분리하여 유지보수를 쉽게 할 수 있도록
try ~ except 구문을 제공합니다.
try 블록 수행 중 오류가 발생하면 즉시 except 블록으로 넘어갑니다. 오류가 없으면 except 블록은 무시됩니다.
num = 0
try:
print('1-1 try 시작')
result = 10 / num # ZeroDivisionError 발생 -> except로 점프
print('1-2 try 종료')
except:
print('2. 오류 발생')
print('4. 프로그램 종료')
발생할 것으로 예상되는 오류명을 명시하여 각각 다르게 처리할 수 있습니다.
try:
# result = 10 / 0 # ZeroDivisionError
result = 10 / "0" # TypeError
except ZeroDivisionError:
print('2-1. 0으로 나눌 수 없습니다.')
except TypeError:
print('2-2. 타입이 맞지 않습니다.')
오류의 상세 내용(에러 메시지 등)을 확인하고 싶을 때 as 키워드를 사용합니다.
try:
result = 10 / "0"
except TypeError as e:
print('오류 발생:', e)
print('추가 정보(args):', e.args)
오류 발생 여부와 관계없이, 파일을 닫거나 리소스를 해제하는 등 무조건 실행되어야 하는 코드는 finally에 작성합니다.
try:
f = open('foo.txt', 'w', encoding='utf-8')
a = 10 + bb # 정의되지 않은 변수 bb로 인해 NameError 발생
except Exception as e:
print('오류:', e)
finally:
print('파일을 안전하게 닫습니다.')
f.close()
여러 개의 오류를 하나의 except 블록에서 동시에 처리할 수 있습니다.
try:
a = ['alpha', 'beta']
print(a[2]) # IndexError 발생 가능
b = 4 / 0 # ZeroDivisionError 발생 가능
except (IndexError, ZeroDivisionError) as e:
print(f"에러 발생: {e.args}, 클래스명: {e.__class__.__name__}")
개발자가 의도적으로 오류를 일으킬 때 raise를 사용합니다. 주로 부모 클래스를 상속받는 자식 클래스가 특정 메서드를 반드시 구현(오버라이딩)하도록 강제할 때 유용합니다.
class Bird:
def fly(self):
# 자식 클래스에서 이 메서드를 재정의하지 않으면 에러 발생
raise NotImplementedError
class Eagle(Bird):
# fly()를 오버라이딩 하지 않고 호출하면 에러 발생
def fly(self):
print("독수리는 빠르게 납니다.")
# 정상 작동
eagle = Eagle()
eagle.fly()
요약:
1. try: 실제 코드를 수행하는 곳
2. except: 발생한 에러를 잡아서 처리하는 곳
3. finally: 에러 유무와 상관없이 마무리 작업을 하는 곳
4. raise: 일부러 에러를 던지는 곳