python

[Python] python 예외처리 try, except, else, finally

seokhyun2 2020. 6. 20. 20:47

실제 서비스를 개발하다보면, 예외처리가 점점 중요해집니다.

서비스가 갑자기 죽어서도 안되고, 에러에 대해서 잘 기록해둬서 버그를 수정해야하니까요.

 

그래서 이번엔 Python에서의 예외처리를 어떻게 하는지 한번 공부해보았습니다.

 

1. Python 예외처리

Python에서는 try, except, else, finally라는 4개의 구문이 있고, 이 4가지를 활용하여 예외처리를 수행합니다.

우선 4개의 구문에 대해서 간단하게 알아보겠습니다.

- try 절에서는 기본적으로 실행할 소스코드를 작성합니다.

- except는 try에서 실행한 소스코드에서 에러가 났을 경우에 실행되는 코드를 작성합니다.

- else 절은 try 절에서 실행한 코드가 에러 없이 정상적으로 동작한 경우에 실행될 코드를 작성합니다.

- finally 절은 위에서 에러가 발생 유무에 상관없이 실행될 코드를 작성합니다.

 

바로 예제를 한번 같이 보도록 하겠습니다.

아래의 주석은 소스코드 실행 결과를 제가 입력한 것입니다.

왼쪽의 경우, 1/0이 zero division에 대한 에러가 발생하여 try 절은 실행되지 않아서 예외가 발생하여 except 절이 실행이 되었고, 그렇기 때문에 else 절은 건너뛰고 finally 절이 실행되어 error와 hi가 출력이 되었습니다.

오른쪽의 경우에는 1/1이 정상적으로 수행이 되어 1.0이라는 결과를 출력하고 에러가 안 났기 때문에 else로 넘어가서 no error를 출력한 뒤, 에러 유무와 상관없이 finally 절에서 hi를 출력하도록 동작하였습니다.

 

기본적인 python 예외처리는 이게 끝입니다. 참 쉽죠?

하지만 실제 서비스에서는 try 절 안에 위와 같이 한 줄만 작성하지 않고, 수십 줄 수백 줄을 입력하기도 합니다.

위의 예제처럼만 코드를 짜게되면, error가 발생했다는 사실은 알 수 있지만, 어떤 에러가 발생한건지는 전혀 알 수가 없습니다.

 

버그를 수정할 때, 물론 디버깅을 하면서 수정하면 되겠지만 어떤 특정 에러가 발생한 것인지 알 수 있으면 좀 더 쉽게 디버깅을 할 수도 있고 서비스 시에도 사용자에게 어떤 문제가 있는지 정보를 제공할 수 있게 됩니다.

 

그래서 예외처리를 좀 더 잘 활용하는 방법도 알아보도록 하겠습니다. 

 

2. 특정 예외 처리하기

먼저, 특정 예외에 대해서만 처리하는 방법입니다. 코드를 보면서 알아보겠습니다.

try:
    10/0    
except ZeroDivisionError:
    print('zero division problem')

위의 코드는 ZeroDivisionError가 발생하였을때만 예외처리를 하는 코드입니다.

try 절에서 10을 0으로 나누어 ZeroDivisionError가 발생하였으므로 위의 코드를 실행하면 'zero division problem'이 출력이 됩니다.

except를 여러번 쓸수도 있습니다. 아래와 같이 작성하면 ZeroDivisionError를 제외한 다른 모든 에러는 마지막 except 절이 실행되게 됩니다.

try:
    x = [10]
    print(x[5])
except ZeroDivisionError:
    print('zero division problem')
except:
    print('no zero division problem')

print(x[5])를 실행하려고 하면, index 문제로 에러가 발생할텐데 예외처리를 위와 같이 해주면 ZeroDivisionError가 아니므로 'no zero division problem'이 출력됩니다.

 

아래와 같이 예외처리를 할 수도 있습니다.

try:
    x = [10]
    print(x[5])
except ZeroDivisionError:
    print('zero division problem')
except IndexError:
    print('index problem')
except:
    print('no zero division or index problem')

위의 경우는 ZeroDivisionError와 IndexError는 별도로 다른 문구를 출력하고 나머지 error는 'no zero division or index problem'이 출력되도록 예외처리합니다. 위 코드를 실행했을 땐 'index problem'이 출력됩니다.

 

3. 에러 메세지 받아서 출력

에러 메세지를 받아서도 출력할 수 있습니다.

try:
    x = [10]
    print(x[5])
except ZeroDivisionError as e:
    print(e)
except IndexError as e:
    print(e)
except Exception as e:
    print(e)

여기서는 as e라는 코드를 추가하여 e를 print하였습니다.

as e를 추가하면 e에 에러 메세지가 저장됩니다.

그래서 그 e를 출력하면 에러 메세지가 출력이 됩니다.

3개의 except 중에서 제일 아래에 있는 except Exception as e는 모든 에러를 처리할 수 있습니다.

 

4. 사용자 정의 error

Exception을 상속 받는 class를 작성하여, error를 정의하여 사용할 수도 있습니다.

class NotEvenError(Exception):
    def __init__(self):
        super().__init__('not even number')

try:
    x = 3
    if x % 2 != 0:
        raise NotEvenError
    print(x)
except Exception as e:
    print('Exception:', e)

위와 같이 코드를 작성하면 if 문에서 raise NotEvenError를 실행하면서 print(x)가 실행되지 않고 except 절로 넘어가게 되고, e를 받아서 출력하면 위에서 작성한 'not even number'라는 에러 메세지가 출력됩니다.

 

위의 방법들을 잘 활용해서 예외처리를 잘 작성하면 더 예쁜 코드가 될 수 있습니다!