[부스트캠프 AI Tech] U-stage. 1-5

느린 개발자·2021년 1월 22일
2

부스트캠프 AI Tech

목록 보기
6/35

📌 Life is short, you need python


📄 Exception/File/Log Handling

✏️ Exception Handling

사용자의 모든 반응을 예상하여 프로그램을 만드는 것은 생각보다 쉬운일이 아니다. 그렇지만 예상치 못한 반응으로 프로그램이 비정상적으로 작동되는것을 막기위해서 예외(Exception) 핸들링 이 필요하다.

  1. 예상 가능한 예외

    • 발생 여부를 사전에 인지할 수 있는 예외
    • 사용자의 잘못된 입력, 파일 호출시 파일 없음
    • 개발자가 반드시 명시적으로 정의
  2. 예상 불가능한 예외

    • 인터프리터 과정에서 발생하는 예외
    • 개발자의 실수로 인해 발생
    • ZeroDivisionError, IndexError..
    • 수행불가시 인터프리터가 자동호출

파이썬에서는 예외처리를 위해 try~except~finally ,try~except~else 구문을 제공해준다.

for i in range(10):
    try:
        result=10/i
    except ZeroDivisionError as e:
        print('Not divided by 0')
    else:
        print('예외가 발생하지 않았을 때 동작합니다')
    finally:
        print('예외 발생 여부와 상관없이 무조건 실행됩니다.')
    print('--------------------------------------------------')

만약 사용자의 반응이 프로그램에 큰 악영향을 끼칠수 있을경우 프로그램의 작동을 멈추는 것이 최선의 선택일수도 있다. raiseassert 를 통해 예외를 발생시킬 수 있다.

user_input=input('음이 아닌 정수를 입력해주세요 : ')
for digit in user_input:
    if digit not in '0123456789':
    	raise ValueError('음이 아닌 정수를 입력해주세요)     
def append_int(src,data):
    assert isinstance(src,list) # list가 아니면 예외
    assert isinstance(data,int) # int가 아니면 예외
    src.append(data)

✏️ File Handling

기본적으로 파일은 text 파일binary 파일 로 나뉜다. 물론 모든 text 파일도 실제로는 binary 파일이지만 ASCII/UNICODE 등 인코딩 형식에 따라 문자열집합으로 변환되어 사람이 읽을수 있다.

Binary 파일Text 파일
컴퓨터만 이해할 수 있는 형태인 이진법 형식으로 저장된 파일인간도 이해할 수 있는 문자열 형식으로 저장된 파일
일반적으로 메모장으로 열면 내용이 깨져보인다메모장으로 열면 확인 가능
엑셀파일,워드파일 등메모장에 저장된 파일, HTML 파일, 파이썬 코드파일 등

파이썬에서는 기본적으로 다음과 같이 파일핸들링이 이루어진다.

파일모드설명
r읽기모드 - 파일을 읽기만 할 때 사용 (디폴트)
w쓰기모드 - 파일에 내용을 쓸 때 사용(내용이 있을경우 지우고 새로쓴다)
a추가모드 - 파일의 마지막에 새로운 내용을 추가 시킬때 사용
t텍스트파일 - 텍스트 문자 기록에 사용 (디폴트)
b바이너리파일 - 바이트 단위 데이터 기록에 사용
f=open('boostcamp.txt','r')
contents=f.read() # 모든 데이터를 문자열로 읽어옵니다.
print(contents)
f.close() # 파일을 닫아줘야합니다.

#################################
# 파일을 닫는게 귀찮다면 with를 이용합시다.
with open('boostcamp.txt','r') as f: 
    line=f.readline() # 데이터를 한줄씩 읽어온다.
    print(line)
    
#################################

with open('boostcamp.txt','r') as f:
    lines=f.readlines() # 모든 데이터를 list로 반환한다.
    print(lines)

#################################
# encoding 규칙은 상황에 맞게 정합니다.
with open('boostcamp.txt','a',encoding='utf-8') as f:
    for i in range(1,6):
	f.write(f'{i}번째 학습정리입니다.') # 데이터를 파일에 저장합니다.

일반적으로 텍스트를 파일로 저장할 때는 파일 입출력을 이용하지만, 리스트나 클래스 같은 객체의 경우 데이터를 저장하거나 불러올 수 없다. 그래서 파이썬에서는 이와 같은 텍스트 이외의 데이터를 파일로 저장하기 위해 pickle 모듈을 제공한다.

import pickle

class Multiply:
    def __init__(self,multiplier):
        self.multiplier=multiplier
    
    def multiply(self,number):
        return number*self.multiplier

calculator=Multiply(5)
print(calculator.multiply(10)) #50

# 객체 저장
with open('multiply_object.pickle','wb') as f:
    pickle.dump(calculator,f)

del calculator # 객체 삭제

# 객체 로드
with open('multiply_object.pickle','rb') as f:
    calculator_pickle=pickle.load(f)
    print(calculator_pickle.multiply(5)) # 25

<참고>
위의 예제들을 살펴보면 파일 핸들링을 위해서는 file path를 다뤄야 한다. 그런데 운영체제에 따라 path 표현방식이 달라 문제가 생기는 경우가 있다. 그래서 최근에는 pathlib 모듈을 사용하여 path 자체를 객체로 사용하여 다루기도 한다.

✏️ Log Handling

프로그램을 개발하면 개발자가 의도한대로 작동하지 않는 경우가 상당히 자주 나온다. 그래서 로그(Log) 는 시스템 발생 장애 및 이상 징후를 모니터링 할 수 있는 좋은 판단 기준이다. 이를 위해 파이썬에서는 logging 모듈을 제공한다.

Level개요예시
debug개발시 처리 기록을 남겨야하는 로그정보를 남김- 다음함수로 A를 호출함
- 변수 A를 무엇으로 변경함
info처리가 진행되는 동안의 정보를 알림- 서버가 시작되었음
- 서버가 종료됨
- 사용자 A가 프로그램에 접속함
warning사용자가 잘못 입력한 정보나 처리는 가능하나, 원래 개발시 의도치 않는 정보가 들어왔을때 알림- str 입력을 기대했으나, int가 입력됨
  -> str casting 으로 처리함
- 함수에 argument로 이차원 리스트를 기대했으나 일차원리스트가 들어옴
  -> 이차원으로 변환후 처리
error잘못된 처리로 인해 에러가 났으나, 프로그램은 동작할수있음을 알림- 파일에 기록을 해야하는데 파일이 없음
  -> Exception 처리 후 사용자에게 알림
- 외부서비스와 연결 불가
critical잘못된 처리로 데이터 손실이나 더이상 프로그램이 동작할 수 없음을 알림- 잘못된 접근으로 해당 파일이 삭제됨
- 사용자의 의한 강제종료.
import logging

#Stream(콘솔)에 로그 남기기
logging.debug('debug log')
logging.info('info log')
logging.warning('warning log')
logging.error('error log')
logging.critical('critical log')

# WARNING:root:warning log
# ERROR:root:error log   
# CRITICAL:root:critical log

debug,info level 이 나오지 않는 이유 는 기본적으로 loggingdefault level 이 warning 으로 되어 있기 때문이다. 만약 level을 변경하고 싶다면 다음과 같이 설정한다.


import logging

logging.basicConfig(level=logging.DEBUG) # DEBUG level 설정

logging.debug('info log')
logging.info('info log')
logging.warning('info log')
logging.error('info log')
logging.critical('info log')

# DEBUG:root:debug log
# INFO:root:info log
# WARNING:root:warning log
# ERROR:root:error log
# CRITICAL:root:critical log

만약 로그 형식 변경로그를 파일로 기록 하고 싶다면 다음과 같이 설정한다.

import logging

#logger instance 생성 
logger=logging.getLogger() 

#logger formatter 생성
#logRecode attributes
formatter=logging.Formatter('[%(asctime)s][%(levelname)s]|[%(filename)s:%(lineno)s]>> %(message)s')  

#logger level 셋팅 
logger.setLevel(logging.DEBUG)

# file & stream handler 생성
file_handler=logging.FileHandler('logging_example.log') # 로그 파일 핸들러
stream_handler=logging.StreamHandler() # 로그 스트림(콘솔) 핸들러

# handler 에 formatter 설정
file_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)

# logger instance에 handler 등록, 스트림과 파일에 동시 로그 출력
logger.addHandler(file_handler)
logger.addHandler(stream_handler)

logger.debug('debug_test')
logger.info('info_test')
logger.warning('warning_test')
logger.error('error_test')
logger.critical('critical_test')

# [2021-01-23 00:30:53,444][DEBUG]|[logging_example.py:45]>> debug_test
# [2021-01-23 00:30:53,445][INFO]|[logging_example.py:46]>> info_test
# [2021-01-23 00:30:53,447][WARNING]|[logging_example.py:47]>> warning_test
# [2021-01-23 00:30:53,449][ERROR]|[logging_example.py:48]>> error_test  
# [2021-01-23 00:30:53,450][CRITICAL]|[logging_example.py:49]>> critical_test

📄 Configparser & Argparser

✏️ Configparser

프로그램을 만들다보면, 상황에 따라 설정파일의 변동이 있다. 예를들어, 파일들의 주소, 출력파일을 저장할 디렉토리 주소 등이다. 이와 같이 프로그램을 실행시킬때마다 설정을 다르게 해주고 싶을 때 유용한 configparser 모듈이 있다.


#config.cfg

[SectionOne]
Status:Single
Age:20
Single:True

[SectionTwo]
FavortieColor=Green
import configparser

config=configparser.ConfigParser()
config.read('config.cfg') # Config 파일 읽어옵니다.

print(config.sections()) # Config 파일의 섹션 정보를 가져옵니다, ['SectionOne','SectionTwo']

for key in config['SectionOne']: # dict 자료형처럼 사용가능합니다.
    print(key) # status,age,single

print(config['SectionOne']['status']) # 'SectionOne' 에 있는 'status' 값을 가져옵니다. # Single

✏️ Argparser

파이썬 프로그램이나 커맨드라인에서 인자 옵션을 주었던 경험이 있을 것이다. 이와 같이 console 창에서 프로그램 실행시 setting 정보를 저장할수 있도록 도와주는 argparse 모듈이 있다.

#parser_example.py
import argparse

parser=argparse.ArgumentParser(description='Argparser example')

parser.add_argument('-a','--a_value',dest='A_value',help='A integers',type=int)
parser.add_argument('-b','--b_value',dest='B_value',help='B integers',type=int)

args=parser.parse_args()
print(args)
print(args.A_value)
print(args.B_value)
>> parser_example.py -a 4 --b_value 5 
Namespace(A_value=4,B_value=5)
4
5

📚 Reference

Logging 예제
Logging level diagram

profile
남들보단 느리지만, 끝을 향해

0개의 댓글