[Python] 에러 및 에러처리

Jae Gyeong Lee·2024년 9월 18일

1. 에러

1.1. 에러 종류(자주 마주하는)

1.1.0) Exception

  • 모든 에러의 상위, 모든 에러에 대해 출력

1.1.1) TypeError

  • 함수에 전달될 값의 type이 잘못된 경우 발생
def add_fuc(a,b):
    c = a + b
    return c

add_fuc(1, '2')

>>> TypeError: unsupported operand type(s) for +: 'int' and 'str'

1.1.2) SyntaxError

  • 문법에 오류가 있는 경우 발생
for a in range(5)
    print(a)

SyntaxError: invalid syntax

1.1.3) IndexError

  • index 범위가 벗어난 경우 발생
list_data = [1,2,3,4,5]
list_data[5]

>>> IndexError: list index out of range

1.1.4) ValueError

  • 부적절한 값이 인자로 들어온 경우 발생
int('a')

>>> ValueError: invalid literal for int() with base 10: 'a'
  • 참조할(찾을) 값이 없는 경우 발생
list_data = [1,2,3,4,5]
list_data.index(7)

>>> ValueError: 7 is not in list

1.1.5) NameError

  • 선언되지 않은 변수가 사용된 경우 발생
a = '가'; b = 'A'
print(c)

NameError: name 'c' is not defined

1.1.6) AttributeError

  • 특정 모듈에 존재하지 않는 메서드(attribute)를 호출하려는 경우 발생
전제: calculator.py 파일에는 아래 2가지 함수가 저장되어 있음

def add(a,b):
    c = a + b
    return c

def minus(a,b):
    c = a-b
    return c
import calculator
calculator.add(1,2)
>>> 3

calculator.minus(1,2)
>>> -1

calculator.divide(1,2)
>>> AttributeError: module 'calculator' has no attribute 'divide'    

1.1.7) KeyError

  • Dictionary에 존재하지 않는 key 값에 접근하려는 경우 발생
test_dic  = {'Name' : '홍길동',
             'Age' : 30,
             'Job' : 'Manager'}

test_dic['Etc']

>>> KeyError: 'Etc'

1.1.8) ModulenotfoundError, ImportError

  • 잘못된 모듈을 호출하려는 경우 발생

(1) ModulenotfoundError

  • 존재하지 않는 모듈을 import 하려는 경우 발생
import tqdmm  #정확한 방법: import tqdm

>>> ModuleNotFoundError: No module named 'tqdmm'

ㄴ tqdmm이란 모듈은 존재하지 않음

(2) ImportError

  • 존재하는 모듈이나 모듈 내 특정 객체가 존재하지 않는 경우 발생
from tqdm import tqd #정확한 방법: from tqdm import tqdm

>>> ImportError: cannot import name 'tqd' from 'tqdm'

ㄴ tqdm란 모듈은 존재하나 tqd는 존재하지 않음

1.1.9) FileNotFoundError

  • 존재하지 않는 파일에 접근하려는 경우 발생

2. 에러 발생 시키기(raise)

명시적으로 에러를 발생시키고자 하는 경우, 에러 발생을 원하는 위치에 작성

$ raise {발생시킬 예러 종류}("에러 메시지")
ㄴ 예) raise ValueError("부적절한 값이 인자로 들어옴")

2.1. 함수 안에서 처리

try:
    a = int(input())
    
    if a % 2 != 0:
        raise ValueError(f'{a}는 2의 배수가 아님')
    elif a == 0 :
        raise Exception(f'{a}은 입력 불가')
        
    print(f'*****{a}는 2의 배수임*****')
    
except ValueError as e:
    print('에러:', e)    
except Exception as e2:
    print('에러:', e2)

# 위 코드에서 ValueError()의 인자로 들어간 메시지가 except ValueError as e: 에서의 e로 반환
# 위 코드에서 ExceptionError()의 인자로 들어간 메시지가 except Exception as e2: 에서의 e2로 반환

# if a % 2 != 0: 또는 elif a == 0: 에 의해 raise문이 실행될 시, raise 밑에 있는 print는 무시

2.2. 함수 밖에서 처리

def test_fuc():
    a = int(input())
    
    if a % 2 != 0:
        raise ValueError(f'{a}는 2의 배수가 아님')
    elif a == 0 :
        raise Exception(f'{a}은 입력 불가')
        
    print(f'*****{a}는 2의 배수임*****')

if __name__ == "__main__":
    try:
        test_fuc()
    except ValueError as e:
        print('에러:', e)    
    except Exception as e2:
        print('에러:', e2)
        
# 함수 안에서(test_fuc()) try-except으로 에러처리를 위한 print문을 넣어주지 않아도, 
# 함수 밖에서 try-except으로 에러처리를 위한 print문을 넣고, 처리해 줄 수 있음.

3. 예외처리(try-except + else, finally)

try:
    에러가 발생할 수 있는 코드

except {발생한 에러1} as e:
    에러1 발생 시 수행할 코드
    
except {발생한 에러2} as e:
    에러2 발생 시 수행할 코드
    
else:
    try문에서 에러 미발생 시 수행할 코드

finally:
    에러 발생 유무와 관계없이 무조건 수행할 코드

### except 문은 2개 이상 추가해 줄 수 있음

3.1. try

  • 예외가 발생할 수 있는 코드를 포함

3.2. except

  • try문에서 예외 발생 시 실행되는 코드
    ㄴ try문에서 예외 미발생 시 실행되지 않음
  • except문을 여러개 사용해, try문에서 발생한 예외에 따른 처리도 가능
try:
    A = int(input("분자: ")); B = int(input("분모: "))
    result = A / B
    print(f"정답: {result}")

except ValueError:
    print("유효하지 않은 값이 들어감", )

except ZeroDivisionError:
    print("0으로 나눌 순 없음")

except Exception as e: # 위 2개 외 모든 예외 처리
    print(f"예상치 못한 에러 발생: {e}")

3.3. else

  • try문에서 예외 미발생 시 실행되는 코드
    ㄴ 즉, except 구문 미발생 시 실행되는 코드
try:
    A = int(input("분자: ")); B = int(input("분모: "))
    result = A / B
    print(f"정답: {result}")

except Exception as e: # 위 2개 외 모든 예외 처리
    print(f"예상치 못한 에러 발생: {e}")
    
else:
    print('try구문 정상 출력')   

3.4. finally

  • try문 예외 발생 여부와 관계없이, 무조건 실행되는 코드
    ㄴ 다시말해, except 구문 발생 여부와 관계없이, 무조건 실행되는 코드
try:
    A = int(input("분자: ")); B = int(input("분모: "))
    result = A / B
    print(f"정답: {result}")

except Exception as e: # 위 2개 외 모든 예외 처리
    print(f"예상치 못한 에러 발생: {e}")
    
else:
    print('try구문 정상 출력')
    
finally:
    print(); print('코드 실행 끝')

3.5. try-except 사용 방법

3.5.1. 발생 에러 포함 x

try:
    ...

except:
    ...

#try문에서 예외가 발생하면, 그 예외가 무엇인지 상관없이 except문 실행    

3.5.2. 발생 에러 포함 o

try:
    ...
except {발생한 에러}:
    ...

#except문에 지정한 에러가 발생했을 때만 except문 실행

3.5.3. 발생 에러 포함 o + 에러 변수 포함 o

try:
    ...
except {발생한 에러} as {에러 변수}:
    ...
    
#except문에서 지정한 에러 발생했을 때 except문 실행, 에러 내용도 알고 싶을 때 사용

3.6. try-finally 사용 방법

try:
    ...
finally:
    ...
    
#try문에서의 예외 발생 여부와 관계없이, 무조건 수행되어야 하는 코드가 있을 때 사용.
#항상 특정 파일을 닫아줘야 하는 경우 사용됨(예, f.close())

4. 사용자 정의 에러

Exception 클래스 상속을 통해 사용자가 직접 정의한 에러를 만들 수 있음

  • Exception은 에러 관련 최상위 클래스
  • 1.1. 에러 종류의 것들은 Python 내장 에러

4.1. 방법1: 출력할 에러메시지를 바로 넣는 경우

class {에러명}(Exception):
    def __init__(self):
        super().__init__('출력할 에러메시지')
class UserdefineError(Exception):
    def __init__(self):
        super().__init__('Error Error Error')

try:
    a = int(input())
    
    if a % 2 != 0:
        raise UserdefineError

except UserdefineError as e:
    print(e)
    print(f'사용자 정의 에러: {a}는 2의 배수가 아님')
    
>>> 3
>>> Error Error Error, 1
>>> 사용자 정의 에러: 3는 2의 배수가 아님

4.2. 방법2: 출력할 에러메시지를 바로 넣지 않은 경우

class {에러명}(Exception):
    pass
class UserdefineError(Exception):
    pass
    
try:
    a = int(input())
    
    if a % 2 != 0:
        raise UserdefineError('Error Error Error, 2')

except UserdefineError as e:
    print(e)
    print(f'사용자 정의 에러: {a}는 2의 배수가 아님')

>>> 3
>>> Error Error Error, 2
>>> 사용자 정의 에러: 3는 2의 배수가 아님

4.3. 방법3: 출력할 에러메시지를 바로 넣는 경우2

class {에러명}(Exception):
    def __str__(self):
        return '출력할 에러메시지'
class UserdefineError(Exception):
    def __str__(self):
        return 'Error Error Error, 3'

try:
    a = int(input())
    
    if a % 2 != 0:
        raise UserdefineError

except UserdefineError as e:
    print(e)
    print(f'사용자 정의 에러: {a}는 2의 배수가 아님')
    
>>> 3
>>> Error Error Error, 3
>>> 사용자 정의 에러: 3는 2의 배수가 아님
profile
안녕하세요 반갑습니다. 공부한 내용들을 기록하고 있습니다.

0개의 댓글