예외(exception)란 코드를 실행하는 중에 발생한 에러를 뜻합니다.
오늘은 try: except: 이용한 예외 처리 예제를 풀어보겠습니다!
(1) try에 실행할 코드를 넣고 except에 예외가 발생했을 때 처리하는 코드를 넣습니다.
try:
실행할 코드
except:
예외가 발생했을 때 처리하는 코드
else:
try 블록 안의 코드가 예외 없이 실행되었을 때 실행
finally:
예외 발생 여부와 상관없이 항상 실행
(보통 파일이나 네트워크 연결 등 리소스를 정리할 때 사용)
try:
x = int(input("정수를 입력하세요: "))
result = 10 / x
except ValueError:
print("정수를 입력해야 합니다.")
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
else:
print("결과:", result)
finally:
print("예외처리가 완료되었습니다.")
(2) 이제 숫자를 0으로 나누었을 때 발생하는 예외를 처리해보겠습니다.
try:
x = int(input('나눌 숫자를 입력하세요: '))
y = 10 / x
print(y)
except: # 예외가 발생했을 때 실행됨
print('예외가 발생했습니다.')
[결과]
나눌 숫자를 입력하세요: 0 (입력)
예외가 발생했습니다.
(1) except에 예외 이름을 지정해서 특정 예외가 발생했을 때만 처리 코드를 실행하도록 만들어보겠습니다.
def div(n1, n2):
print('나눗셈 연산')
try:
n1 = float(n1)
except:
print('첫 번째 피연산자는 숫자가 아닙니다.')
return
try:
n2 = float(n2)
except:
print('두 번째 피연산자는 숫자가 아닙니다.')
return
if n2 == 0:
print('0으로 나눌 수 없습니다.')
return # 멈춤
print(f'{n1} / {n2} = {n1 / n2}')
🏷️만약 2번째 숫자가 0이면 나눗셈을 할 수 없음.
이런 경우 위와 같이 씀.
(2) 이번에는 ZeroDivisionError를 이용해 만들어 보겠습니다.
def div(n1, n2):
print('나눗셈 연산')
try:
n1 = float(n1)
except:
print('첫 번째 피연산자는 숫자가 아닙니다.')
return
try:
n2 = float(n2)
except:
print('두 번째 피연산자는 숫자가 아닙니다.')
return
try:
print(f'{n1} / {n2} = {n1 / n2}')
except ZeroDivisionError as e:
print(e)
print('0으로 나눌 수 없습니다.')
🏷️ZeroDivisionError : 0으로 나눴을때 발생하는 에러
Q> 사용자가 입력한 숫자를 이용해서 산술연산 결과를 출력하는 모듈을 만들되, 예상하는 예외에 대한 예외처리 코드를 작성
[calculator.py]
# 예외 처리 = try, except 이용
def add(n1, n2):
print('덧셈 연산')
try: # 숫자로 변경
n1 = float(n1)
except: # 숫자가 아니면 예외가 발생하게 만들어 주기!
print('첫 번째 피연산자는 숫자가 아닙니다.')
return # 계쏙 실행하면, 에러가 날 것. 따라서 return으로 종료 시켜 줌
try:
n2 = float(n2)
except:
print('두 번째 피연산자는 숫자가 아닙니다.')
return
print(f'{n1} + {n2} = {n1 + n2}') # 마지막에 연산 함수 입력
def sub(n1, n2):
print('뺄셈 연산')
try:
n1 = float(n1)
except:
print('첫 번째 피연산자는 숫자가 아닙니다.')
return
try:
n2 = float(n2)
except:
print('두 번째 피연산자는 숫자가 아닙니다.')
return
print(f'{n1} - {n2} = {n1 - n2}')
def mul(n1, n2):
print('곱셈 연산')
try:
n1 = float(n1)
except:
print('첫 번째 피연산자는 숫자가 아닙니다.')
return
try:
n2 = float(n2)
except:
print('두 번째 피연산자는 숫자가 아닙니다.')
return
print(f'{n1} * {n2} = {n1 * n2}')
def div(n1, n2):
print('나눗셈 연산')
try:
n1 = float(n1)
except:
print('첫 번째 피연산자는 숫자가 아닙니다.')
return
try:
n2 = float(n2)
except:
print('두 번째 피연산자는 숫자가 아닙니다.')
return
# 만약 2번째 숫자가 0이면 나눗셈을 할 수 없음.
# 이런 경우 아래와 같이 씀.
if n2 == 0:
print('0으로 나눌 수 없습니다.')
return # 멈춤
print(f'{n1} / {n2} = {n1 / n2}')
# ZeroDivisionError : 0으로 나눴을때 발생하는 에러 CLASS (원래 있는 함수!)
# ▲ if n2 == 0: ~ print(4줄) 대체 가능
# try:
# print(f'{n1} / {n2} = {n1 / n2}')
# except ZeroDivisionError as e:
# print(e)
# print('0으로 나눌 수 없습니다.')
def mod(n1, n2):
print('나머지 연산')
try:
n1 = float(n1)
except:
print('첫 번째 피연산자는 숫자가 아닙니다.')
return
try:
n2 = float(n2)
except:
print('두 번째 피연산자는 숫자가 아닙니다.')
return
if n2 == 0:
print('0으로 나눌 수 없습니다.')
return
print(f'{n1} % {n2} = {n1 % n2}')
def flo(n1, n2):
print('몫 연산')
try:
n1 = float(n1)
except:
print('첫 번째 피연산자는 숫자가 아닙니다.')
return
try:
n2 = float(n2)
except:
print('두 번째 피연산자는 숫자가 아닙니다.')
return
if n2 == 0:
print('0으로 나눌 수 없습니다.')
return
print(f'{n1} // {n2} = {int(n1 // n2)}')
def exp(n1, n2):
print('거듭제곱 연산')
try:
n1 = float(n1)
except:
print('첫 번째 피연산자는 숫자가 아닙니다.')
return
try:
n2 = float(n2)
except:
print('두 번째 피연산자는 숫자가 아닙니다.')
return
print(f'{n1} ** {n2} = {n1 ** n2}')
[ex.py]
import calcularot as cc
num1 = input('첫 번째 연산자 : ')
num2 = input('두 번째 연산자 : ')
cc.add(num1, num2)
cc.sub(num1, num2)
cc.mul(num1, num2)
cc.div(num1, num2)
cc.mod(num1, num2)
cc.flo(num1, num2)
cc.exp(num1, num2)
Q> 1부터 1000까지의 소수인 난수 10개를 생성, 소수가 아니면 사용자 예외가 발생
[prime_module.py]
class NotPrimeException(Exception):
def __init__(self, n):
super().__init__(f'{n} is not prime number.')
class PrimeException(Exception):
def __init__(self, n):
super().__init__(f'{n} is prime number.')
#소수를 구하는 구조
def isPrime(number):
flag = True
for n in range(2, number):
if number % n == 0:
flag = False
break
# 소수가 아니면
if flag == False:
raise NotPrimeException(number)
# 소수인 경우
else:
raise PrimeException(number)
import random # 난수 발생
import prime_module as pm # 소수 유무 모듈
primeNumbers = [] # 자료구조 만들어주기
n = 0
while n < 10: #10개가 나올때 까지 반복해야 함
rn = random.randint(2, 1000)
if rn not in primeNumbers:
#중복체크(=리스트에 없다면)
try:
pm.isPrime(rn)
except pm.NotPrimeException as e: # 소수가 아니다
print(e)
continue # 필요 없으니까 반복 재실행
except pm.PrimeException as e: #소수다
print(e)
primeNumbers.append(rn) # primeNumbers 리스트에 추가
else:
print(f'{rn} is overlap number.') #중복 숫자 발생 시
continue
n += 1
print(f'PrimeNumbers: {primeNumbers}')
# 전체적으로 소수값을 나열하는 값
몇개의 변수가 들어올지 모를때 변수 앞에 사용
def calculate(*gcs):
for을 이용한 시퀀스의 인덱스를 반복할때는 enumerate를 사용
for word in enumerate(['A', 'B', 'C'])
print(word)
(0, 'A')
(1, 'B')
(2, 'C')
예제 중 중요한 부분 톱아보기
globals()
함수를 쓰면
g1price, g2price...를 {g}Price
로 참조할 수 있음
여기서 {g}
는 g{idx+1}
라서 globals()(f'{g}Price')
가 하나의 변수로 치환 됨.
(g{idx+1} = g1, g2, g3 ....을 뜻 함)
따라서
totalPrice += globals()[f'{g}price'] * gcsDic[g]
는
totalPrice
는 g1
인 경우 1,200원 * 갯수
로 해석이 가능
Q> 1부터 1000까지의 소수인 난수 10개를 생성, 소수가 아니면 사용자 예외가 발생
[calculatePurchase.py]
# 상품의 가격 설정
g1price = 1200; g2price = 1000; g3price = 800
g4price = 2000; g5price = 900
def formatedNumber(n):
return format(n, ',')
# ▼사용자가 갯수를 입력하면 총 금액을 출력하는 함수를 만들어야 함
def calculate(*gcs): #변수 : gcs, * : 몇개의 변수가 들어올지 모를때 변수 앞에 사용
gcsDic = {} # 상품 목록화 딕셔너리 # 정상적인 상품
againCntInput = {} # 미결제 상품 #비정상적인 상품
for idx, gc in enumerate(gcs):
try:
gcsDic[f'g{idx+1}'] = int(gc) # 상품1번idx+1 = 구매 갯수int(gc)
except Exception as e:
againCntInput[f'g{idx+1}'] = gc
print(e)
totalPrice = 0
for g in gcsDic.keys(): #정상적인 상품 계산
totalPrice += globals()[f'{g}price'] * gcsDic[g]
print('---------------------------')
print(f'총 구매 금액: {formatedNumber(totalPrice)}원')
print('-------- 미결제 항목 --------')
for g in againCntInput.keys():
print(f'상품: {g},\t 구매 개수: {againCntInput[g]}')
print('---------------------------')
[ex.py]
import calculatePurchase as cp
g1Cnt = input('goods1 구매 개수: ')
g2Cnt = input('goods2 구매 개수: ')
g3Cnt = input('goods3 구매 개수: ')
g4Cnt = input('goods4 구매 개수: ')
g5Cnt = input('goods5 구매 개수: ')
cp.calculate(g1Cnt, g2Cnt, g3Cnt, g4Cnt, g5Cnt)
Q> 회원가입 정보 입력 만들기
[mem.py]
#예외 클래스 생성
# 비어있는 정보가 있으면 EmptyDataException 발생
class EmptyDataException(Exception):
#어떤 값이 비어있는지 알아야 하니까, i 하나 지정
def __init__(self, i):
super().__init__(f'{i} is empty!')
def checkInputData(n, m, p, a, ph):
if n == '':
raise EmptyDataException('name')
elif m == '':
raise EmptyDataException('mail')
elif p == '':
raise EmptyDataException('password')
elif a == '':
raise EmptyDataException('address')
elif ph == '':
raise EmptyDataException('phone')
else:
return True
#회원 가입 모듈
class RegisteMember():
# 정보를 다 받고
def __init__(self, n, m, p, a, ph):
self.m_name = n
self.m_mail = m
self.m_pw = p
self.m_addr = a
self.m_phone = ph
print('Membership completed!!')
# 회원정보 출력
def printMemberInfo(self):
print(f'm_name: {self.m_name}')
print(f'm_mail: {self.m_mail}')
print(f'm_pw: {self.m_pw}')
print(f'm_addr: {self.m_addr}')
print(f'm_phone: {self.m_phone}')
[ex.py]
import mem
m_name = input('이름 입력: ')
m_mail = input('메일 주소 입력: ')
m_pw = input('비밀번호 입력: ')
m_addr = input('주소 입력: ')
m_phone = input('연락처 입력: ')
try:
mem.checkInputData(m_name, m_mail, m_pw, m_addr, m_phone)
newMember = mem.RegisteMember(m_name, m_mail, m_pw, m_addr, m_phone)
newMember.printMemberInfo()
except mem.EmptyDataException as e:
print(e)
값의 존재 여부 검사, 순서 반복
(1) 특정 값의 존재 여부 검사
in 키워드는 어떤 값이 리스트, 튜플, 세트의 요소인지 아닌지 여부를 판단하는 데 사용됩니다.
해당 값이 있으면 True를 없으면 False를 반환합니다.
(2) 반복문에서 순서를 반복
영화 제목이 담긴 리스트가 있고 이 리스트의 요소를 for문을 이용해서 차례대로 출력하고 싶다면 다음과 같이 코드를 작성할 수 있습니다.
movies_of_2019 = ['The Irishman', 'Little Women', 'John Wick: Chapter 3', 'Ford v Ferrari']
for title in movies_of_2019:
print(title)
"""
The Irishman
Little Women
John Wick: Chapter 3
Ford v Ferrari
"""
Q> 은행 입출금, 잔액 프로그램
🏷️__init__
메소드라서 중간 중간 새로운 정의 추가가 가능
위 예제를 여러 단계로 나눠 봐야 한다.
(1) 개인통장, (2) 은행 정보, (3) 잔고 부족
▼
(1) 개인 통장에 대한 class 만들기
(2) 은행에 대한 class 만들기
(3) 잔고 부족 class 만들기
(4) 출력을 위한 문구