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

업데이트:

개요

jpg

작업을 하다보면 예상하지 못한 수많은 오류들(빨간줄..)을 만나게 된다. 특히 데이터 핸들링할때 if문 등으로 오류자체가 발생하지 않도록 고려해 줄 수도 있겠지만, 그것보다 예외처리를 통해 처리하는 것이 훨씬 효율적인 방법이라는 것을 기억하자.
이번 포스팅에서는 발생하는 오류들을 회피하거나, 처리하는 방법에 대해 알아보자.

크게 5가지를 활용 할 수 있다.

  1. try : 실행코드(오류가 발생하나 보자!)
  2. except : 예외처리 코드(오류가 발생하면 이걸 실행해줘!)
  3. else : 예외처리할 오류가 없을때 실행되는 코드
  4. finally : 오류 발생여부 상관 없이 무조건 실행되는 코드
  5. raise : 오류를 일부러 발생시키기


1. try & except

먼저 숫자가 아닌 문자열을 int함수로 변경할때의 예제로 알아보자.

int("number")
ValueError: invalid literal for int() with base 10: 'number'

그러면 위와 같은 오류가 발생한다.

try:
    int("number")
except:
    print("Not Number!")
Not Number!

try문을 실행하면 ValueError가 발생한다(숫자가 아니므로, 정수변경 불가). 이럴때 위와 같이 구성하면, 발생하는 오류에 대해 except절의 코드가 실행된다.
(단, 오류의 종류에 상관없이 무조건 예외처리)

try:
    int("number")
except ValueError:
    print("Not Number!")

위 구성은 발생할 오류를 생각하고 ValueError를 처리하고 싶을때 사용하면 된다.

try:
    int("number")
except ValueError as m:
    print(m)

위 구성은 ValueError발생 시 저장되어 있는 string을 출력해준다.


2. try & except & else

이제 그 뒤에 else문을 추가하면 에러가 발생하지 않았을 때 실행될 코드를 구성할 수 있다.

try:
    int("11")
except ValueError as m:
    print(m)
else:
    print("No Error!")
No Error!


3. try & except & else & finally

finally 까지 추가를 하면 에러발생과 관계없이 항상 실행되는 코드를 추가로 구성할 수 있다.
(이는 Error발생으로 동작이 제한될 가능성을 회피하기 위함이다)
예시를 위해 for문으로 정상인 경우(11)와 에러발생(number)의 경우를 구성했다.

for _ in ["11","number"]:
    try:
        int(_)
    except ValueError as m:
        print(m)
    else:
        print("No Error!")
    finally:
        print("Finally Code")
    print("\n")
No Error!
Finally Code


invalid literal for int() with base 10: 'number'
Finally Code
  • 첫번째 루프 : 에러가 발생하지 않으므로 else절과 finally절이 실행되었다.
  • 두번째 루프 : 에러가 발생했으므로 except절과 finally절이 실행되었다.


4. 여러 개의 오류 예외처리

예외처리는 except문으로 할 수 있다고 했다. 위에서는 모든 오류의 예외처리와, 특정 오류의 예외처리를 했었지만 여러개의 오류를 처리하기 위해서는 다음과 같이 구성하면 된다.

for st_ in [{}, "number"]:
    try:
        int(st_)
    except ValueError as m:
        print(m)
    except TypeError as m:
        print(m)
    print("\n")
int() argument must be a string, a bytes-like object or a number, not 'dict'


invalid literal for int() with base 10: 'number'

위와 같이 st_라는 객체가 가변적인 경우 ValueError외에도 발생할 오류가 존재한다. 이럴때 활용하면 좋다.


5. 오류 회피

단순히 오류를 회피하고 다음 실행코드로 넘어가버리고 싶을때는 pass를 활용하면 된다.
(참고 : pass, continue, break 차이)

try:
    int("number")
except ValueError:
    pass


6. 사용자 정의 오류 및 일부러 발생시키기

코드 상의 오류는 없지만, 조건문을 활용하듯 오류를 일부러 발생시키고 싶을때도 있다. 또한 이러한 오류를 직접 만들 수도 있다.
먼저 사용자 정의 오류의 생성방식을 알아보자.

python의 Exception클래스를 상속받아 만들 수 있다.

class MyError(Exception):
    def __init__(self, msg='init_error_msg'):
        self.msg = msg
    
    def __str__(self):
        return self.msg

raise MyError("MyError")
MyError: MyError
  • __init__ : 에러 클래스 생성 시 실행되는 함수로 msg의 내용을 지정한다.
  • __str__ : 에러가 발생할때 출력해주는 메세지를 리턴해주는 함수이다(지정하지 않을 시 __init__함수의 초기 메세지를 출력한다).

자 그럼 오류도 만들었으니, 직접 오류를 발생시켜보자. raise를 활용하면 된다.

def input_cores():
    try: 
        core_ = input("input your cores (max 10):")
        if int(core_) > 10:
            raise MyError("Exceeded the limit!")
        print("Cores : ", core_)
    except MyError as e:
        print(e)    
        input_cores()
    except ValueError as e:
        print(e)
        input_cores()

위 함수는 사용할 코어의 수를 지정하도록 도와준다. 사용자가 지정한 코어가 10을 초과하거나 숫자가 아닌 값을 입력할때 발생하는 오류를 예외처리하고, 다시 함수를 재귀적으로 호출하여 코어를 다시 지정하도록 한다.

input_cores()

input your cores (max 10):100
>>> Exceeded the limit!

input your cores (max 10):30
>>> Exceeded the limit!

input your cores (max 10):aaaa
>>> invalid literal for int() with base 10: 'aaaa'

input your cores (max 10):5
>>> Cores :  5


Reference

https://gomguard.tistory.com/122

https://wikidocs.net/30

댓글남기기