[Python] 예외 처리 (try ~ except)


Study/Python  2019. 12. 12. 20:11

안녕하세요. 명월입니다.


이 글은 Python에서 예외 처리에 대한 글입니다.


프로그램을 작성하다 보면 여러가지 에러를 만나는 경우가 많습니다. 예를 들면 string 타입과 int타입을 더한다던가, 문자 타입을 정수형 타입으로 변형을 한다던가입니다.

a = "hello";
b = 1;
# 문자형 타입 a변수와 숫자형 타입 b를 더한다.
c = a + b;
# 결과를 출력한다.
print(c);
# a를 출력한다.
print(a);

위 예제처럼 4번째 줄에 에러가 나왔다고 표시가 됩니다. 여러가지 입력 변수를 잘못 받아서 잘못된 타입으로 더하게 되는 경우가 있는데 이럴 때 이렇게 잘못 되었다고 에러가 발생하는 건 나쁜건 아닙니다.

그러나 에러가 발생하면 스크립트는 그 즉시 중단을 하기 때문에 이건 문제가 될 수 습니다. 위 예제에서도 print(a)가 실행되지 않았습니다.


그래서 예외 처리가 있는데 예외 처리를 하면 에러를 넘어갈 수 있습니다.

a = "hello";
b = 1;
# 에러가 발생할 수 있는 구간을 try ~ except 구간으로 지정한다. 에러가 발생하게 되면 except로 넘어갈 것이다.
try:
  c = a + b;
  print(c);
except:
  print("the error is occurred");

print(a);

위 예제는 제가 try ~ except 구간으로 에러가 발생할 수 있는 구간을 정해서 에러가 발생하면 except를 호출하게 했습니다.

물론 에러가 발생하지 않으면 except는 호출되지 않습니다.


구간내에 하나의 에러 뿐아닌 많은 에러가 발생할 수 있습니다. 그 에러의 구분마다 에러처리를 다르게 할 수도 있습니다.

def division_function(a,b):
  try:
    # a에 b를 나눈다.
    print(a/b);
  # 이 에러는 타입이 맞지 않는 변수 값으로 계산을 하려할 때 발생, 즉 str타입 / int 타입이면 에러가 발생한다.
  except TypeError as e:
    print(e);
  # 이 에러는 0으로 나누려고 할 때, 발생하는 에러입니다.
  except ZeroDivisionError as e:
    print(e);

# TypeError가 발생할 것을 예상
division_function("a", 1);
# ZeroDivisionError가 발생할 것을 예상
division_function(1, 0);
# 정상 처리된다.
division_function(4, 2);

위 결과를 보면 division_function를 세번 호출하는데 위 두번은 에러가 두 번 발생합니다.

두 에러는 에러 타입이 다른 것으로 서로 다른 except를 호출하게 되는 것입니다.


참고로 「에러 타입 as e」를 사용하면 e변수에 에러의 내용이 변수에 들어가게 됩니다.

여기서 참고로 에러 타입을 한 번에 다잡는 타입은 Exception 타입입니다.

def division_function(a,b):
  try:
    print(a/b);
  # 가장 최상의 에러 타입을 가장 위에 배치
  except Exception as e:
    print("first");
  except TypeError as e:
    print("second");
  except ZeroDivisionError as e:
    print("third");
  
division_function("a", 1);
division_function(1, 0);
division_function(4, 2);

위 처럼 작성하게 되면 TypeError과 ZeroDivisionError이 발생해도 전부 Exception으로 호출이 됩니다.

def division_function(a,b):
  try:
    print(a/b);
  except TypeError as e:
    print("first");
  except ZeroDivisionError as e:
    print("second");
  # 최상의 에러 타입이 가장 아래에 배치
  except Exception as e:
    print("third");
  
division_function("a", 1);
division_function(1, 0);
division_function(4, 2);

위 결과는 TypeError와 ZeroDivisionError를 각각 호출하였습니다.


위 예제에서 다시 예외가 발생하고 최종적으로 데이터를 처리해야 하는 경우네는 finally입니다. 이는 에러가 발생해도 발생하지 않아도 반드시 호출되는 키워드입니다.

def division_function(a,b):
  try:
    # 이번에는 결과를 return했습니다.
    return a/b;
  except TypeError as e:
    # 에러가 발생하면 -1를 return합니다.
    return -1;
  except ZeroDivisionError as e:
    # 에러가 발생하면 -2를 return합니다.
    return -2;
  except Exception as e:
    # 에러가 발생하면 -3를 return합니다.
    return -3;
  finally:
    print("finally!");
  
ret = division_function("a", 1);
print(ret);
ret = division_function(1, 0);
print(ret);
ret = division_function(4, 2);
print(ret);

일반 문법에서는 finally를 사용하나 안하나 except가 호출되면 다음 라인이 실행이 되기 때문에 finally의 필요성을 잘 못 느끼는데, return이랑 같이 사용하면 try안에서 return이 되더라도 finally가 실행되기 때문에, 리소스 관리등에서 자주 사용하는 키워드입니다.


여기까지는 에러가 발생하면 처리하는 방법에 대해 소개했습니다. 이번에는 우리가 에러를 발생시켜 보겠습니다.

def call_function():
  raise Exception("error!!!!")
  
call_function();

raise키워드에 Exception를 호출하게 되면 에러가 발생하게 됩니다.

def call_function():
  raise Exception("error!!!!")

try:
  call_function();
except Exception as e:
  print(e);
  
print("end");

call_function를 호출하면 에러가 발생할 것을 인지하여 try~except로 다시 에러처리를 했습니다.


여기까지 Python에서 예외 처리에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.