ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 14. 파이썬 에러와 예외처리 (2) try except
    파이썬(Python) 강의 2019. 3. 20. 14:39

    이번 포스트에서는 파이썬 try except 문법을 이용해 하나의 예외를 처리 하는 법을 알아보도록 하겠다.

    들어가기전에

     이 포스트는 여러분이 파이썬을 설치했고 각자 원하는 IDE를 이용해 파이썬을 개발한다고 가정한다. 혹시 파이썬을 설치하지 않았다면  1.파이썬 설치 및 개발환경 설정 이 포스트에서 파이썬과 파이썬 개발환경을 먼저 셋업하길 바란다. 앞서 말했듯이 반드시 실습 해 보길 바란다. 이 포스트는 여러분이 파이썬의 주요 자료형과 함수를 알고있고 사용 할 수 있다고 가정한다. 또한 여러분은 파이썬 에러와 예외를 알고 있다. 

    목표

    • try: except:
    • try: except Error:
    • 예외 정보
    • 예외 전이(Exception Propagation)
    • 예외시 아무것도 안하기

    try: except:

    많은 프로그래밍 언어에서는 예외를 처리 할 수 있는 exception 문법을 제공한다. (예: 자바/C++ try {} catch () {}) 파이썬에서는 try except 구문을 제공한다. 신택스는 다음과 같다.

    try:
    // 로직
    except:
    // 해당 예외 발생 시 해야 할 일

    try 블록은 예외가 발생 할만한 로직을 포함한다. 예외는 발생 할 수도있고 발생하지 않을 수도 있다. 예외가 발생하고 그 예외가 except구문의 <예외 이름>과 맞으면 해당 로직은 수행하던 것을 멈추고 예외 처리 블록으로 넘어간다. 

    try:
    doSomething1()
    doSomething2() --> 예외 발생!
    doSomething3()
    doSomething4()
    except :
    print("예외 발생!")

    예를 들어서 try 블록 안에서 함수 4개를 실행한다고 하자. doSomething2이라는 함수에서 예외가 발생하면, 즉시 실행을멈추고 except로 넘어간다. 만약 이 예외가 except하고자 하는 예외(<예외 이름>)과 같다면, 예외처리 블록(print("예외 발생!"))을 실행시키고 그게 아니라면 해당 예외를 처리하지 않는다. 처리되지 않은 예외는 이 함수를 call한 함수로 전이(propagate)된다. 예를들어 알아보자.

    try:
    prin()
    except :
    print("예외 발생!") 실행 결과: 예외 발생!

    예외가 왜 발생했는가? 그렇다 prin이라는 함수가 존재하지 않기 때문이다. 따라서 NameError라는 예외가 발생하고 except구문으로 넘어가 예외를 처리한다.

    try:
    print("1")
    print("2")
    prin("3")
    print("4")
    except :
    print("예외 발생!") 실행 결과: 1 2 예외 발생!

    이제 위의 코드를 실행 해 보자. 1과 2를 출력 하 후 3을 출력하려던 도중 예외가 발생한다. 따라서 파이썬은 prin("3")의 실행을 중단하고 except로 넘어간다. 위와 같은 방법으로 모든 예외를 처리 할 수 있다. 하지만 모든 예외를 이렇게 처리하는게 좋은 디자인일까? 때에 따라 다르다. 어떤 경우에는 예외의 종류마다 다르게 예외처리를 해 주고 싶을 수 있다. 대표적인 경우는 예외에 따라 다른 예외 메시지를 출력하고 싶은 경우이다. 예외에 따라 메시지를 다르게 출력하면 디버깅에 용이 할 수 있다. 그 밖에도 많은 경우에서 예외를 다르게 처리하고 싶을 때가 있다. 

    try: except Error:

    try:
    print("1")
    print("2")
    prin("3")
    print("4")
    except NameError:
    print("예외 발생!") 실행 결과: 1 2 예외 발생!

    except와 :사이에 처리하고 싶은 예외를 넣으면 해당 예외만 처리 할 수 있다. 위의 경우 NameError가 발생하므로 예외 발생!이 출력된다.

    try:
    print("1")
    print("2")
    prin("3")
    print("4")
    except EOFError:
    print("예외 발생!") 실행 결과: 1 2 Traceback (most recent call last): File "/Users/../PycharmProjects/MyFirstProject/helloworld.py", line 4, in <module> prin("3") NameError: name 'prin' is not defined

    prin("3")에서는 NameError가 난다. 하지만 우리는 NameError를 예외처리 하지 않으므로 예외가 전이(propagate)된다.

    예외 정보

    어떤 예외에 대한 정보를 확인하고 싶다면 어떻게 해야 할까?

    def main():
    try:
    print("1")
    print("2")
    prin("3")
    print("4")
    except NameError as e:
    print("예외 발생! main ", e.args)
    print(e.__traceback__)

    main() 실행 결과: 1 2 예외 발생! main ("name 'prin' is not defined",) <traceback object at 0x100764208>

    as <변수이름>문법을 이용해 현재 넘어온 예외 오브젝트를 접근 할 수 있다. 해당 오브젝트는 예외의 종류나 예외 메시지 등을 가지고 있다.

    예외 전이(Exception Propagation)

    예외의 전이란, 예외가 발생한 부분이 해당 예외를 처리하지 않는 경우 이 예외를 부른 함수로 예외가 전달 되는 것을 의미한다. 다음의 예를 보자.

    def doSomething():
    try:
    print("1")
    print("2")
    prin("3")
    print("4")
    except NameError:
    print("예외 발생 doSomething!")


    doSomething() 실행 결과: 1 2 예외 발생 doSomething!

    위의 예를 보면 doSomething함수 내부에서 예외가 발생하고, 해당 예외를 doSomethine내에서 처리한다. 이제 아래의 예를 보자.

    def doSomething ():
    print("1")
    print("2")
    prin("3")
    print("4")

    def main():
    try:
    doSomething()
    except NameError:
    print("예외 발생! main")

    main() 실행 결과: 1 2 예외 발생! main

    위의 예를 보면 예외는 doSomething안에서 발생하다. 하지만 doSomething안에는 예외를 처리하는 except구문이 없다. 따라서 이 예외는 doSomething을 부른 main 함수로 전이(propagate)되고 main에서 NameError를 처리하기 때문에 "예외 발생! main"이 출력된다. 만약 두개 모두 있다면 어떻게 될까?

    def doSomething ():
    try:
    print("1")
    print("2")
    prin("3")
    print("4")
    except NameError:
    print("예외 발생! doSomething")

    def main():
    try:
    print("main 1")
    doSomething()
    print("main 2")
    except NameError:
    print("예외 발생! main")

    main() 실행 결과: main 1 1 2 예외 발생! doSomething main 2

    main에도 예외 처리 구분이 있지만 doSomething내에도 예외 처리가 있기때문에 여기서 예외가 처리되므로 main함수로 예외가 전달되지 않는다. doSomething은 1과 2를 출력하고 예외를 처리한 후 리턴한다. 따라서 main함수의 코드는 아무런 영향 없이 끝까지 잘 실행된다. 따라서 어떤 함수에서 예외가 발생했을 때 그 함수가 예외를 적절히 처리한다면 이 함수를 부른 함수는 아무 영향 없이 진행 할 수 있다는 뜻이다.

     이번 포스트에서는 try except구문을 이용해 하나의 예외를 처리하는 방법에 대해 알아보았다. 다음 포스트에서는 여러개의 예외를 하나의 try 구문에서 처리하는 방법에 대해 알아보도록 하겠다.

    댓글

f.software engineer @ All Right Reserved