About Python – “예외처리 – try, except, finally, raise”
About Python – “예외처리 – try, except, finally, raise”
예외 처리란?
예외 처리(例外 處理) 또는 오류 처리는 일반적인 실행의 흐름을 바꾸는 몇 가지 조건을 처리하도록 설계한 프로그래밍 언어의 개념이나 컴퓨터 하드웨어 구조를 말한다.
일반적으로 프로그램이 처리되는 동안 특정한 문제가 일어났을 때 처리를 중단하고 다른 처리를 하는 것을 예외 처리라고 한다.
위키백과
여러 상황에서 발생하는 오류를 무시하고 다른 작업을 처리하는 것을 예외 처리라고 합니다.
파이썬의 try, except
문
print(x)
# NameError: name 'x' is not defined
위의 코드는 정의되지 않은 x
를 사용하려고 했기 때문에 오류가 발생합니다.
위의 오류를 try, except
문을 사용하여 예외 처리를 해 보겠습니다. 먼저 파이썬의 try, except
문은 다음과 같이 사용합니다.
try:
# 오류가 발생할 가능성이 있는 내용
# 오류가 발생하면 except 블록을 수행
except:
# 오류가 발생하면 수행될 내용
아래의 코드와 같이 예외처리를 할 수 있습니다.
try:
print(x)
except:
print("프로그램에 오류가 발생하였습니다.")
# 프로그램에 오류가 발생하였습니다.
기본적인 try, except
문은 오류가 발생하기만 하면 except
블록을 수행하도록 합니다. NameError
가 발생했지만 예외처리가 되는 것을 확인할 수 있습니다.
try:
print(x)
except IndexError:
# except [발생한 오류]: 로 해당 오류가 발생했을 때에만 예외처리를 하도록 할 수 있습니다.
print("프로그램에 오류가 발생하였습니다.")
# 프로그램에 오류가 발생하였습니다.
위의 코드의 경우 try
블록에서 NameError
가 발생하지만, IndexError
에 관한 except
문을 작성했으므로 예외처리가 되지 않는 것을 확인할 수 있습니다. 아래처럼 여러 개의 오류를 처리하도록 할 수 있습니다.
try:
print(x)
a = 1229/0
except IndexError:
print("IndexError 발생!")
except NameError:
print("NameError 발생!")
except ZeroDivisionError:
print("ZeroDivisionError 발생!")
# NameError 발생!
위의 try
블록의 코드를 살펴봅시다. print(x)
에서는 NameError
가, 1229/0
에서는 ZeroDivisionError
가 발생할 것이 자명해 보입니다. 하지만 맨 처음 발생한 NameError
가 발생한 후 except
문이 수행되어 그 이후의 오류는 발생하지 않았습니다.
아래의 경우처럼 여러 종류의 오류를 동시에 처리하기 위해서는 괄호 안에 오류의 종류를 묶어주면 됩니다.
try:
print(x)
a = 1229/0
except (IndexError, NameError, ZeroDivisionError) as e:
print(e)
except [발생한 오류] as [변수]
와 같이 코드를 작성하면 변수
에 오류 메시지가 담깁니다.
try:
print(x)
except NameError as a:
print(a)
print(type(a))
# <class 'NameError'>
# name 'x' is not defined
아래와 같이 pass
라는 키워드를 사용해서 오류가 발생해도 아무것도 하지 않고 오류를 회피하도록 할 수 있습니다.
try:
print(x)
except NameError as a:
pass
파이썬의 try, finally
문
try, finally
문을 사용하면 에러 발생 여부와는 상관없이 finally
문 아래의 블록이 수행됩니다.
try:
print(x)
finally:
print("finally는 에러 발생 여부와 상관없이 수행됩니다.")
# NameError: name 'x' is not defined
# finally는 에러 발생 여부와 상관없이 수행됩니다.
try
에서 에러가 발생했고 그것과는 관계없이 finally
블록이 수행되는 것을 확인할 수 있습니다.
try:
# x = 1
print(x)
except NameError as e:
print(e)
finally:
print("finally는 에러 발생 여부와 상관없이 수행됩니다.")
# NameError: name 'x' is not defined
# finally는 에러 발생 여부와 상관없이 수행됩니다.
2줄의 주석을 풀고 위의 코드를 실행해 보아도 finally
블록은 수행되는 것을 확인할 수 있습니다.
파이썬의 raise
명령어
try:
raise NameError
finally:
pass
# NameError
위처럼, raise
라는 명령어를 통해서 에러를 일부러 발생시킬 수 있습니다.
파이썬의 Exception 클래스
여러 오류들의 종류인 NameError, IndexError
와 같은 것들은 파이썬에서 내장 클래스로 정의되어 있습니다. 전에 파이썬의 클래스를 설명할 때에 클래스를 종이접기 책에 비유한 적이 있는데, 마찬가지로 우리는 Exception
클래스를 상속하여 원하는 예외의 종류를 만들 수 있습니다.
class NoError(Exception):
def __str__(self):
return "no를 입력하지 마세요!"
def yesOrYes(yes):
if yes == "no":
raise NoError
print(yes)
try:
yesOrYes("no")
except NoError as e:
print(e)
# no를 입력하지 마세요!
위의 1줄에서 3줄까지의 코드를 보면 Exception
클래스를 상속받은 나만의 예외 NoError
를 정의했습니다. 밑의 __str__
메서드는 오류 메시지를 출력할 때에 호출되는 메소드입니다.
밑의 yesOrYes()
함수를 정의한 내용(5줄에서 8줄까지의 코드)을 살펴보겠습니다. 매개변수로 “no
“가 들어오면 위에서 만들었던 나만의 예외인 NoError
를 발생하도록 되어 있네요.
그러면 10줄에서 13줄까지의 코드처럼 예외처리를 할 수 있습니다. yesOrYes("no")
로 함수를 호출하였기 때문에 만들었던 NoError
가 발생하고, 그것의 메시지인 "no를 입력하지 마세요!"
가 출력되는 것을 확인할 수 있습니다.