본문 바로가기
지식공학/Python

Python 독학 기본편 #10 에러처리

by Eric87 2020. 10. 21.
반응형

어려운 class를 넘어가서 오늘 배울 내용은 쉽습니다. 우리가 만든 코드에 에러가 발생하는 경우 어디서, 무엇 때문에 발생한 에러인지 확인을 할 수 있도록 에러를 색출하는 방법을 알아볼 것입니다. 이 라이브러리를 사용함으로써 장차 본인이 만든 앱에 완성도를 높일 수 있습니다. 그럼 시작하겠습니다. 잘 따라오세요.

나누기를 하는 계산기를 만들어 보겠습니다. 지금까지 배운 내용으로 충분히 작성할 수 있죠? 아직 익숙하지 않아 힘들다면 제가 쓴 코드를 해석할 수 있는 수준이도 괜찮습니다.

print("나누기 전용 계산기입니다.")
num1 = int(input("첫 번째 숫자를 입력하세요 : "))
num2 = int(input("두 번째 숫자를 입력하세요 : "))
print("{0} / {1} = {2}".format(num1, num2, int(num1/num2)))

num이라는 변수에 input명령어를 사용해서 사용자로부터 숫자 정보를 받습니다. 파이썬에서 input은 모두 문자 형태로 받아들이므로 int를 사용해서 input을 감싸주었습니다. 그럼 python에서는 input으로 받은 내용을 정수 형태로 읽어 들입니다. 8 나누기 4를 하면 2가 계산되고 8 나누기 5를 하면 1.6이 아니라 1이 출력이 됩니다. 왜냐하면 int(num1/num2) 때문이죠 int는 정수이기 때문에 소수점이 버리고 정수만 표시를 합니다. 여하튼 잘 계산이 되는 것을 확인할 수 있습니다. 여기에 우리는 일부러 에러를 발생해 보겠습니다. input으로 숫자가 아닌 문자를 입력하면 연산을 할 수 없기 때문에 에러가 발생이 되고 또 두 번째 input에 0을 입력하면 나누기 에러가 발생하겠죠? (0으로 나눌 수 없기 때문에) 그럴 경우 우리가 원하는 방법으로 에러를 표현할 수 있습니다. 저는 "에러! 잘못된 값을 입력하였습니다."로 표현을 해 보겠습니다.

try:
     print("나누기 전용 계산기입니다.")
     num1 = int(input("첫 번째 숫자를 입력하세요 : "))
     num2 = int(input("두 번째 숫자를 입력하세요 : "))
     print("{0} / {1} = {2}".format(num1, num2, int(num1/num2)))
except ValueError:
     print("에러! 잘못된 값을 입력하였습니다.")
except ZeroDivisionError as err:
     print(err)

try라는 라이브러리를 사용해서 앞에서 작성한 계산기 코드를 넣어주고 except를 써서 valueerror를 넣어 주었습니다. 파이썬에서는 잘못된 문자 값(엄밀히 말하면 자료의 형태)을 읽을 수 있습니다. 그리고 print를 활용해서 "에러! 잘못된 값을 입력하였습니다."을 넣었습니다. 여기까지만 입력하고 실행을 합니다. 그리고 8과 문자인 a를 입력하면 "에러! 잘못된 값을 입력하였습니다."가 출력되는 것을 확인할 수 있습니다. 0으로 입력한 값에 대해서는 자료 형태가 잘못되지 않기 때문해당 문장이 출력되지 않습니다. 하지만 ZeroZeroDivisionError를 넣어줌으로써 0으로 나누는 오류를 검출할 수 있고 as err를 입력해주면 에러의 원인을 알려줍니다.

다음으로 계산기 코드를 약간 수정하겠습니다. 앞서 배운 list를 활용해서 num을 묶어 보겠습니다.

try:
     print("나누기 전용 계산기입니다.")
     nums = []
     nums.append(int(input("첫 번째 숫자를 입력하세요 : ")))
     nums.append(int(input("두 번째 숫자를 입력하세요 : ")))
     nums.append(int(nums[0] / nums[1]))
     print("{0} / {1} = {2}".format(nums[0], nums[1], nums[2]))
except ValueError:
     print("에러! 잘못된 값을 입력하였습니다.")
except ZeroDivisionError as err:
     print(err)

nums로 빈 리스트를 만들고 append를 활용해서 입력받은 두 개의 num과 연산으로 생성되는 num을 넣었습니다. 만약 여기서 주석처리(#)를 활용해서 세 번째 num을 비활성화하여 실행을 하면 에러가 발생합니다. ValueError도 아니고 ZeroDivisionError도 아닙니다. 이처럼 아무런 에러가 아닐 때는 다음을 작성해 주면 됩니다.

except:
     print("알 수 없는 에러가 발생하였습니다.")

이것을 입력하고 실행을 하면 "알 수 없는 에러가 발생하였습니다."가 출력되는 것을 알 수 있습니다.

어떤 에러인지 모르기 때문에 위에서 했던 코드에 as error를 넣어보겠습니다.

except Exception as err:
     print("알 수 없는 에러가 발생하였습니다.")
     print(err)

이렇게 하고 실행을 하면 list index out of range라는 에러가 뜨는 것을 확인할 수 있습니다. list에는 두 개의 num밖에 없는데 print로 3개를 출력하라고 하니 list에 없는 값이라고 알려주는 것입니다.

이걸 조건문(if)과 혼합하여 특정 조건이 되면 에러가 표시되도록 할 수 있습니다. 지금 만든 계산기 코드가 간단해서 큰 수를 연산할 수 없어 한 자릿수만 나눌 수 있다고 가정해 봅시다. 그래서 input으로 받는 값이 10 이상이면 연산을 할 수 없습니다.

try:
     print("한 자리 숫자 나누기 전용 계산기입니다.")
     num1 = int(input("첫 번째 숫자를 입력하세요 : "))
     num2 = int(input("두 번째 숫자를 입력하세요 : "))
     if num1 >= 10 or num2 >10:
          raise ValueError
     print("{0} / {1} = {2}".format(num1, num2, int(num1 / num2)))
except ValueError:
     print("잘못된 값을 입력하였습니다. 한 자리 숫자만 입력하세요.")

if문을 사용해서 num1 또는 num2가 10 이상이면 ValueError를 활성시키라는 의미입니다. 실행을 시켜 10 이상의 숫자를 입력하면 에러 문장이 표현되는 것을 확인할 수 있습니다.

복습으로 저번에 배운 class를 활용해서 표현할 수 있습니다.

class BigNumberError(Exception):
     pass

try:
     print("한 자리 숫자 나누기 전용 계산기입니다.")
     num1 = int(input("첫 번째 숫자를 입력하세요 : "))
     num2 = int(input("두 번째 숫자를 입력하세요 : "))
     if num1 >= 10 or num2 >10:
          raise BigNumberError
     print("{0} / {1} = {2}".format(num1, num2, int(num1 / num2)))
except ValueError:
     print("잘못된 값을 입력하였습니다. 한 자리 숫자만 입력하세요.")
except BigNumberError:
     print("에러가 발생하였습니다. 두 자리 숫자입니다.")

BigNumberError라는 class를 만들어 주고 if문 안에 있는 ValueError를 BigNumberError으로 바꿔줍니다. except BigNumberError를 추가하여 에러 문장을 작성해 주면 에러 발생 시 해당 문장을 출력해줍니다.

너무 class의 내용이 없으니깐 조금 넣어볼게요. 에러를 발생시키는 값을 출력해주는 코드를 추가해 보았습니다.

class BigNumberError(Exception):
     def __init__(self, msg):
          self.msg = msg
     def __str__(self):
          return self.msg

try:
     print("한 자리 숫자 나누기 전용 계산기입니다.")
     num1 = int(input("첫 번째 숫자를 입력하세요 : "))
     num2 = int(input("두 번째 숫자를 입력하세요 : "))
     if num1 >= 10 or num2 >10:
          raise BigNumberError("입력값 : {0}, {1}".format(num1, num2))
     print("{0} / {1} = {2}".format(num1, num2, int(num1 / num2)))
except ValueError:
     print("잘못된 값을 입력하였습니다. 한 자리 숫자만 입력하세요.")
except BigNumberError as err:
     print("에러가 발생하였습니다. 두 자리 숫자입니다.")
     print(err)

class에 __init__을 사용해서 객체를 생성해 주고 함수를 이용해 잘못 입력된 값을 저장하기 위해 msg 저장하고 msg를 내보내라는 의미입니다. 그리고 BigNumberError가 실행이 되면 입력된 값이 나오도록 하였습니다.

마지막으로 finally라는 명령어를 입력하면 에러가 출력되든 출력되지 않든 코드가 실행하고 나면 마지막으로 finally안에 있는 코드를 실행시키는 라이브러리입니다. 이것을 넣어주면 끝맺음을 함으로써 보다 완성도 있는 코드를 작성할 수 있습니다.

반응형

댓글