DX Data School

Python의 Exception Handling(예외처리)

Kim J 2024. 1. 30. 10:05

1) 오류의 종류

> 물리적 오류(Compile Error) : 문법적인 오류

- 전체를 컴파일하고 실행하는 프로그램에서는 이 오류가 있으면 실행하지 않는다.

파이썬이나 자바스크립트의 경우는 괄호나 들여쓰기 오류를 제외하고 일단 실행되는 부분까지는 실행함

물리적 오류는 코드 수정을 통해 해결해야 한다.

> 논리적 오류 : 알고리즘 오류

- 문법적인 오류는 없어서 실행이 잘 되지만 원하는 결과가 만들어지지 않는 경우

디버깅을 통해 해결해야 한다.

[1] 순차적으로 프로그램을 실행시켜 메모리 값을 확인

[2] 부분적으로 폐쇄시키며 문제를 파악

( 중간중간 프린트를 통해 결과가 제대로 출력이 되는지 확인하며 프로그래밍을 진행하면 어디서 오류가 발생 됐는지 파악하기 쉽다. )

> 예외(Exception)

- 문법적인 오류는 없어서 실행이 잘 되지만 실행 도중 문제가 발생해서 에러가 발생하고 프로그램이 중단되는 현상

두 가지 경우로 나누는데 첫째로 런타임 오류로 코드로 해결 할 수 없는 경우가 있고 둘째로 런타임 오류가 아니라서 코드로 해결할 수 없는 경우가 있다.

둘째의 경우 예외 처리를 통해 해결 한다.

> 단언(Assertion)

- 오류는 아니지만 강제로 예외를 발생시키는 것

2) Exception Handling(예외 처리)

> 예외 처리의 목적

[1]예외가 발생하더라도 계속 작업을 수행하기 위해

[2]예외가 발생한 경우 로깅을 하기 위해

> 거의 무조건 예외 처리를 하는 경우 - 자바에서는 강제 : 외부 자원을 사용하는 경우

(외부 자원을 사용하는 경우는 내부에서 만든게 아니라서 존재 여부나 실행 여부를 알 수 없기 때문)

[1] 파일 처리

[2] 네트워크 처리

[3] 데이터베이스 프로그래밍

> 예외처리 기본 코드

try:

예외가 발생할 가능성이 있는 코드

except:

예외가 발생했을 때 수행할 코드

> 예외가 발생해도 프로그램을 이어서 수행

[1] 예외 처리를 하지 않은 경우

def ten_div(x):
    return 10 / x

print(ten_div(3))
print(ten_div(0)) 
print("메인 종료")

실행결과 :

예외 발생으로 print("메인 종료") 수행되지 않았음

[2] 예외 처리를 통해 프로그램이 중단되지 않음

def ten_div(x):
    return 10 / x

try:
    print(ten_div(3))
    print(ten_div(0))
except:
    print("예외 발생")

print("메인 종료")

실행결과 :

[3] 예외를 확인하는 것

def ten_div(x):
    return 10 / x

try:
    print(ten_div(3))
    print(ten_div(0))
except Exception as e:
    print(e)

print("메인 종료")

실행결과 :

3) 예외 종류 별 처리

> 예외 처리 클래스 계층 : Python > https://docs.python.org/3/library/exceptions.html

** 예외 계층

Base Exception

                            SystemExit

                             KeyboardInterrupt

                             GeneralExit

                             Exception

                                                          StopInteration

                                                          ArithmeticError

                                                                                       ZeroDivisionError

                                                          LookupError

                                                                                       IndexError

                                                          SyntaxError

> 예외를 별도로 처리 : except 절은 개수 제한이 없어 클래스 별로 처리 가능

try:

                             예외가 발생 할 가능성이 있는 코드

except 예외 클래스 이름 as 변수 :

                             예외 클래스 이름에 해당하는 예외가 발생했을 때 처리 할 코드

except 예외 클래스 이름 as 변수 :

                             예외 클래스 이름에 해당하는 예외가 발생했을 때 처리 할 코드

except 예외 클래스 이름 as 변수 :

                             예외 클래스 이름에 해당하는 예외가 발생했을 때 처리 할 코드

1.

ar = [10, 20, 30]

print(ar[0])
print(ar[1])
print(ar[3])

실행결과:

IndexError 발생

2.

ar = [10, 20, 30]

try:
    print(ar[0])
    print(ar[1])
    print(ar[3])
except:
    print("예외 발생")

실행결과:

모든 예외가 발생하면 except 실행

3.

ar = [10, 20, 30]

try:
    print(ar[0])
    print(ar[1])
    print(ar[3])
except ZeroDivisionError as e:
    print("예외 발생")

실행결과:

ZeroDivisionError 가 아니므로 IndexError 발생

4.

ar = [10, 20, 30]

try:
    print(ar[0])
    print(ar[1])
    print(ar[3])
except ZeroDivisionError as e:
    print("0으로 나누는 예외 발생")
except IndexError as e:
    print("인덱스 예외 발생")

실행결과:

5.

ar = [10, 20, 30]

try:
    print(ar[0])
    print(ar[1])
    print(ar[3])
except Exception as e:
    print("예외 발생")
except ZeroDivisionError as e:
    print("0으로 나누는 예외 발생")
except IndexError as e:
    print("인덱스 예외 발생")

- 예외 처리에서 except는 위에서 순차적으로 확인해서 자신의 타입과 일치하는 구문을 만나면 처리하고 except를 빠져나간다. 하지만 상위 클래스 타입의 참조형 변수에는 하위 클래스 타입의 인스턴스를 대입할 수 있다. 반대는 불가하다. 위 경우 그렇기 때문에 아래와 같은 실행결과가 출력된다.

실행결과:

아래 코드도 위 같은 이유로 예외처리가 잘못 된 경우이다.

ar = [10, 20, 30]

try:
    print(ar[0])
    print(ar[1] / 0)
    print(ar[3] / 0)
except Exception as e:
    print("예외 발생")
except ZeroDivisionError as e:
    print("0으로 나누는 예외 발생")
except IndexError as e:
    print("인덱스 예외 발생")

실행결과 :

except를 여러 개 작성 할때는 상위 클래스 예외를 하위 클래스 예외보다 아래에 작성해야 한다

순서가 반대로 되면 Not Reachable Code가 만들어 진다.

바르게 수정하면 아래 코드와 같고 그에 따른 실행결과는 달라진다.

ar = [10, 20, 30]

try:
    print(ar[0])
    print(ar[1] / 0)
    print(ar[3] / 0)

except ZeroDivisionError as e:
    print("0으로 나누는 예외 발생")
except IndexError as e:
    print("인덱스 예외 발생")
except Exception as e:
    print("예외 발생")

실행결과 :

4) else 와 finally

> else 는 except 아래에 절을 만들어 예외가 발생하지 않은 경우에 수행 할 로직을 작성

> finally는 예외 발생 여부에 상관없이 수행 할 로직을 작성

( 명시적으로 나타내기 위해 and 스레드에 구애받지 않음)

1) else

ar = [10, 20, 30]

try:
    print(ar[0])
    print(ar[1])
    print(ar[2])

except ZeroDivisionError as e:
    print("0으로 나누는 예외 발생")
except IndexError as e:
    print("인덱스 예외 발생")
except Exception as e:
    print("예외 발생")

else:
    print("예외가 발생하지 않은 경우에 수행")

실행결과:

예외가 발생하지 않았기 때문에 else 를 수행

2) finllay

ar = [10, 20, 30]

try:
    print(ar[0])
    print(ar[1])
    print(ar[3])

except ZeroDivisionError as e:
    print("0으로 나누는 예외 발생")
except IndexError as e:
    print("인덱스 예외 발생")
except Exception as e:
    print("예외 발생")

else:
    print("예외가 발생하지 않은 경우에 수행")

finally:
    print("무조건 수행")

실행결과 :

예외가 발생했기 때문에 예외를 수행 후 finally 수행

5) 단언(Assertion)

 

> 오류는 아니지만 강제로 예외를 발생시키는 것

try:
    x = 10
    if x <20:
        # 강제로 예외를 발생시키기 - 단언
        raise Exception ("숫자가 너무 작음")
    print(x)
except Exception as e:
    print(e)

실행결과 :

머리가 터질거 같아요.......................살려주ㅓ..............................

ㅇㅣ겨내라 김제이............................하이띠....잉...................

 

'DX Data School' 카테고리의 다른 글

Python Web Programming  (0) 2024.01.30
Python 과 Mongo DB 연동  (1) 2024.01.30
NoSQL (MongoDB)  (1) 2024.01.30
Windows Function  (0) 2024.01.30
Transaction 실습  (0) 2024.01.30