학습목표¶
- 예외처리
- 파일 입출력
- 예외? 에러보다는 마일드한 에러(의도하지 않는 상황발생)
- 예외처리를 통해서 예외상황을 알리고 대처할 수 있도록 하는 방법
- 시스템의 비정상적인 종료를 막고 정상적인 흐름으로 시스템을 종료 시키기 위한 방법
- 파이썬 xxxxError -> Exception
- raise xxxxError 발생
- Exception이 예외의 최상위 부모
try : 예외발생 코드 except : try 블록에서 발생된 예외를 처리하는 영역 else : 예외가 발생하지 않았을 떄 수행하는 영역 finally : 예외 발생여부와 상관없이 항상 수행하는 영역
In [8]:
lst = [1,2,3]
try :
for idx in range(len(lst)+1):
print(lst[idx])
except IndexError as e :
print(f'{e} 예외 발생 함')
else :
print('예외가 발생하지 않았을 때 수행하는 블럭')
finally :
print('예외발생 여부와 상관없이 수행하는 블럭')
print('>>>> 정상종료')
1 2 3 list index out of range 예외 발생 함 예외발생 여부와 상관없이 수행하는 블럭 >>>> 정상종료
In [41]:
def getUserInfo():
''' 사용자의 정보를 입력받고, 형식 오류나 유효성을 처리하는 기능'''
try:
name = input('이름을 입력하세요 : ').strip()
if not name.isalpha():
raise ValueError('이름은 문자만 포함해야 합니다!!')
age = input('나이를 입력하세요 : ').strip()
if not age.isdigit():
raise ValueError('나이는 숫자만 입력하세요!!')
age = int(age)
if age < 0 or age > 120:
raise ValueError('1~120 사이의 숫자만 입력하세요!!')
email = input('이메일 주소를 입력하세요 : ').strip()
if '@' not in email or '.' not in email :
raise ValueError('올바를 이메일 형식이 아닙니다!!')
except Exception as ve:
print(f'입력오류 {ve}')
else :
return {
"name" : name,
"age" : age,
"email" : email
}
finally :
print('입력정보를 정상적으로 처리 하였습니다!!')
In [42]:
result = getUserInfo()
print(result)
입력오류 이름은 문자만 포함해야 합니다!! 입력정보를 정상적으로 처리 하였습니다!! None
In [81]:
# Quiz
# 예외처리 관점, 보안적 관점
# 매개변수로 전달받은 리스트타입 요소의 값을 거듭제곱해서 반환하여 출력하고자 한다
def lstPrt(lst: list) -> list:
try:
for idx in range(len(lst)):
value = lst[idx]
value = str(value)
if not value.isdigit():
raise ValueError(f'{value}는 숫자가 아닙니다!')
value = int(value)
print(f'{value ** 2}')
except Exception as e:
print(f'예외 발생: {e}')
else:
print('예외가 발생하지 않았을 때 수행하는 블럭')
finally:
print('예외 발생 여부와 상관없이 수행하는 블럭')
print('>>>> 정상종료')
In [152]:
# Quiz
# 예외처리 관점 (요소의 타입), 보안적 관점(매개변수의 타입)
# 매개변수로 전달받은 리스트타입 요소의 값을 거듭제곱해서 반환하여 출력하고자 한다
# def lstPrt(lst: list) -> list:
# if not isinstance(lst, list):
# raise TypeError('매개변수 타입은 반드시 list 형태')
# result = []
# for data in lst:
# if not isinstance(data, (int, float)):
# print('숫자가 아닌 값이 포함 됨')
# continue
# else :
# result.append(data ** 2)
# return result
import logging
# level
# debug, info, warning, error, critical
# format (%s -%s etc....)
# format key : asctime, levelname, name, message, etc .....z
logging.basicConfig(level=logging.WARNING,
format="%(asctime)s - %(levelname)s - %(message)s", force=True)
# 예외, 보안, 로깅
def lstPrt(lst: list) -> list:
# 보안관점에서 입력검증
if not isinstance(lst, list):
raise TypeError('매개변수 타입은 반드시 list 형태')
result = []
for idx, data in enumerate(lst):
if not isinstance(data, (int, float)):
logging.warning(f'{idx}에 숫자가 아닌 값이 포함된 타입 {type(data).__name__}')
continue
try :
result.append(data ** 2)
except Exception as e:
logging.error(f'예상치 못한 예외 발생 : {e}')
return result
In [153]:
tmp = [10,20,30,40,'seop',50,60]
result = lstPrt(tmp)
print(result)
2025-10-31 14:24:25,296 - WARNING - 4에 숫자가 아닌 값이 포함된 타입 str
[100, 400, 900, 1600, 2500, 3600]
In [87]:
# 에러메시지 노출 - print()
# 서버환경 print() -> 로깅(level=warning/info/error) 일반화된 메시지 제공이 안전
# import logging
import logging
logging.basicConfig(level=logging.WARNING)
data = 'jslim'
try:
print(data ** 2)
except TypeError as t:
logging.warning(f'숫자가 아닌값을 발견 : {data}')
WARNING:root:숫자가 아닌값을 발견 : jslim
In [ ]:
import logging
# level
# debug, info, warning, error, critical
# format (%s -%s etc....)
# format key : asctime, levelname, name, message, etc .....z
logging.basicConfig(level=logging.WARNING,
format="%(asctime)s - %(levelname)s - %(message)s",
filename='shieldus.log',
filemode='a')
파일 입출력¶
- 제공하는 함수는 대부분 예외발생시키고 있음.
- txt, json 허용 (.csv, .xls 분석을 위한 데이터타입이 필요한데 Pandas - DataFrame)
- open(filePath, mode='r|w|a|b', encoding='utf-8')
- with open() as file:
In [183]:
import logging
# level
# debug, info, warning, error, critical
# format (%s -%s etc....)
# format key : asctime, levelname, name, message, etc .....z
logging.basicConfig(level=logging.WARNING,
format="%(asctime)s - %(levelname)s - %(message)s", force=True)
filePath = './data/greeting.txt'.strip()
try :
file = open(filePath, mode='r', encoding='utf-8')
except:
logging.error(f'파일을 열 수 없습니다.')
print('type - ', type(file))
#print('dir - ', dir(file))
print(file.read(), type(file.read())) # str
# print(file.readlines(), type(file.readlines())) # list
file.close()
type - <class '_io.TextIOWrapper'> 강사님과 함께하는 즐겁지 아니하지 아니한 파이썬수업 그렇지만 열공하자 오늘은 즐거운 금요일 불금인데.....방콕이 답이다 <class 'str'>
In [208]:
# with open은 file.close()를 포함하고 있음 안써도 됨
filePath = './data/greeting.txt'.strip()
with open(filePath, mode='r', encoding='utf-8') as file :
lst = file.readlines()
for txt in lst:
print(txt.strip('\n'))
강사님과 함께하는 즐겁지 아니하지 아니한 파이썬수업 그렇지만 열공하자 오늘은 즐거운 금요일 불금인데.....방콕이 답이다
In [213]:
# data = '안녕하세요~ 한 주 수고많으셨구요... 즐거운 금요일 되시길 바랍니다.'
data = {'id' : 'xxxx' , 'pwd' : 'xxxx'}
print('type - ', type(data))
# dict -> json , json -> dict
import json
filePath = './data/msg.json'.strip()
with open(filePath, mode='w', encoding='utf-8') as file :
# file.write(data)
json.dump(data, file)
type - <class 'dict'>
In [217]:
print('json 형식의 파일을 읽어들인다면? - ')
import json
filePath = './data/msg.json'.strip()
with open(filePath, mode='r', encoding='utf-8') as file :
# file.write(data)
loadData = json.load(file)
print(loadData, '-', type(loadData))
print(loadData['id'])
json 형식의 파일을 읽어들인다면? -
{'id': 'xxxx', 'pwd': 'xxxx'} - <class 'dict'>
xxxx
In [350]:
# Quiz
# 사용자의 이름을 두자리만 출력하고 나머지는 마스킹처리(su********)
# 로깅포맷
# 로깅포맷형태를 파일로 저장 userAccess.log
# decorator 이용해서 (보안적인 측면을 강화)
# 예외관련해서 필요한 부분이 있다면 추가
from datetime import datetime
import logging
logging.basicConfig(level=logging.WARNING,
format="%(asctime)s - %(levelname)s - %(message)s", force=True)
filePath = './data/userAccess.log'.strip()
def getProfile(user : dict) -> None :
try :
if not isinstance(user, dict):
raise TypeError('매개변수 타입은 반드시 dict 형태')
start = datetime.today()
name = user['name']
mask = name[:2] + '*' * (len(name) - 2)
end = datetime.today()
time = (end - start)
data = (f'검색한 시간 - {start}, 사용자 - {mask}, 실행시간 정보 - {time}')
with open(filePath, mode='w', encoding='utf-8') as file :
file.write(data)
print(data)
except Exception as e:
logging.error(f'예상치 못한 예외 발생 : {e}')
In [351]:
# caller
user = {'name' : 'superadmin', 'authenticated' : True}
# 관리자가 사용자 정보를 확인하고 한다.
# 관리자가 사용자의 정보를 검색한 시간, 사용자이름, 실행시간 정보를 userAccess.log 파일로 저장하고 싶다면
getProfile(user)
검색한 시간 - 2025-10-31 16:43:06.260883, 사용자 - su********, 실행시간 정보 - 0:00:00.000008
In [355]:
import logging
name = user['name']
print(name)
maskedName = name[:2] + '*' * (len(name) - 2)
print(maskedName)
logging.basicConfig(level=logging.WARNING,
format="%(asctime)s - %(levelname)s - %(message)s", force=True)
superadmin su********
In [ ]:
# Quiz
# 사용자의 이름을 두자리만 출력하고 나머지는 마스킹처리(su********)
# 로깅포맷
# 로깅포맷형태를 파일로 저장 userAccess.log
# decorator 이용해서 (보안적인 측면을 강화)
# 예외관련해서 필요한 부분이 있다면 추가
from time import time, sleep
def secureLog():
def wrapper():
pass
@secureLog
def getProfile(user : dict) -> None :
print(f'{user['name']} 프로필을 관리자가 검색합니다.')
sleep(5)
In [ ]: