예외 처리 - 일부러 오류 발생 시키기, 오류 회피하기

이찬·2023년 7월 8일
0

Python

목록 보기
14/17
post-thumbnail

오류는 어떨 때 발생하는가?

  • 디렉터리 안에 없는 파일을 열려고 시도했을 때 발생
  • 0으로 다른 숫자를 나누는 경우
  • Index 오류

오류 예외 처리 기법

try, except 문

  • try 블록 수행 중 오류가 발생하면 except 블록이 수행된다.
  • try에 실행할 코드를 넣고 except에 예외가 발생했을 때 처리하는 코드를 넣는다.
try:
    x = int(input('나눌 숫자를 입력하세요: '))
    y = 10 / x
    print(y)
except:    # 예외가 발생했을 때 실행됨
    print('예외가 발생했습니다.')

except[발생오류 [as 오류 메시지 변수]] : 특정 예외만 처리하기

try:
   4/0
except ZeroDivisionError as e:
    print(e)

try... finally

  • finally 절은 try문 수행 도중 예외 발생 여부에 상관없이 항상 수행된다.
  • 보통 finally절은 사용한 리소스를 close해야 할 때에 많이 사용한다.
f = open('foo.txt','w')
try:
   # 무언가를 수행
finally :
    f.close()

여러개의 오류 처리

try:
  # ~~
 except ~~ :
   print()
 except ~~ :
   print() 

오류 회피하기

try:
  f = open("나",'r')
except FileNotFoundError:
  pass

try 문 안에서 FileNotFoundError가 발생할 경우 pass를 사용하여 오류를 회피하도록 작성한 예제

오류 일부러 발생시키기

  • 파이썬은 raise 명령어를 통해 오류를 강제로 발생시킬 수 있다.
a = int(input("1~5 까지 숫자 입력 : "))

# 범위를 벗어나면 error 발생!
if a < 1 or a > 5:
    raise

# 범위 안에 있으면 정상 출력
print(f"입력한 a : {a} 입니다.")
  • 1~5 사이의 숫자가 아니라 다른 숫자를 넣게 되면 raise 를 통해서 에러를 발생하도록 한다.

try + raise + except

try:
    a = int(input("1~5 까지 숫자 입력 : "))

    # 범위를 벗어나면 error 발생!
    if a < 1 or a > 5:
        raise

    # 범위 안에 있으면 정상 출력
    print(f"입력한 a : {a} 입니다.")
except:
    print("1~5 사이 입력하라고 했잖아요.")

-동일한 코드를 try + except 구문으로 감싸게 하고 try 안에서 raise 를 통해서 에러를 발생시킬 수 있습니다.
하지만 try + except 로 예외처리를 하고 있으니, 에러로 인해서 프로그램이 중간에 비정상 종료되는 것이 아니라,
except 구문으로 가게되어서 예외처리 되고 있음을 볼 수 있습니다.

예외 만들기 : Exception

  • 프로그래머가 직접 만든 예외를 사용자 정의 예외라고
  • 파이썬 내장 클래스인 Exception 클래스를 상속하여 만들 수 있다.

class MyError (Exception):
pass

  • 그냥 Exception을 상속받아서 새로운 클래스를 만들면 됩니다. 그리고 init 메서드에서 기반 클래스의 init 메서드를 호출하면서 에러 메시지를 넣어주면 됩니다.
def say_nick(nick):
   if nick == "바보":
     raise MyError()
   print(nick)
class BigNumberError(Exception): # 사용자 정의 에러
    pass

try:
    print("한 자리 숫자 나누기 전용 계산기입니다.")
    num1 = int(input("첫 번째 숫자를 입력하세요: "))
    num2 = int(input("두 번째 숫자를 입력하세요: "))
    if num1 >= 10 or num2 >= 10: # 입력받은 수가 한 자리인지 확인
        # raise ValueError
        raise BigNumberError # 사용자 정의 에러
    print("{0} / {1} = {2}".format(num1, num2, int(num1 / num2)))
except ValueError:
    print("잘못된 값을 입력하였습니다. 한 자리 숫자만 입력하세요.")
except BigNumberError: # 사용자 정의 예외 처리
    print("에러가 발생하였습니다. 한 자리 숫자만 입력하세요.")
  • 먼저 두 자리 이상의 수를 입력해서 발생한 에러라는 의미로 BigNumberError 라는 클래스를 만들고 파이썬에서 이미 정의되어 있는 Exception 이라는 클래스를 상속받도록 합니다. 이렇게 하면 앞에서 봤던 ValueError, IndexError 와 비슷하게 사용자가 필요로 하는 어떤 새로운 형태의 Error 를 정의할 수 있습니다.
  • 그리고 입력값이 10 이상인지를 확인하는 if 구문에서 ValueError 대신 새롭게 정의한 BigNumberError 를 발생시키고, except 구문을 추가함으로써 새로운 에러에 대한 예외 처리를 하도록 하겠습니다.
class BigNumberError(Exception): # 사용자 정의 에러
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return self.msg

-이렇게만 해서는 ValueError 와 큰 차이가 없으므로 이번에는 BigNumberError 의 내용을 채워보겠습니다.

  • pass 부분 대신 init() 생성자와 str() 메소드를 추가합니다. 생성자에서는 에러 메시지를 의미하는 msg 를 전달받아서 멤버변수로 설정하고, str() 메소드에서는 멤버변수 msg 를 반환해주도록 합니다. 이제 BigNumberError 를 발생시킬 때 필요한 문구를 추가하여 보다 자세한 에러 내용을 출력할 수 있습니다.
class BigNumberError(Exception):
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return "[에러코드 001] " + self.msg # 에러 메시지 가공
  • 사실 BigNumberError 의 init() 생성자와 str() 메소드는 따로 정의하지 않고 그냥 pass 로만 두어도 동일하게 동작합니다. 하지만 생성자에서 추가로 어떤 작업을 해야 한다거나 str() 메소드에서 에러 메시지를 에러 코드 등과 함께 출력하고 싶은 경우에 다음과 같이 코드를 수정할 수 있습니다.
profile
Kyunghee univ. IE 21

0개의 댓글