-
[python]3. Exception_File_LogHandling인공지능/부스트캠프 Ai Tech 2022. 1. 21. 18:36728x90In [1]:
from IPython.core.display import display, HTML display(HTML("<style>.container { width:90% !important; }</style>")) #창 맞추기위함
In [ ]:try: # 예상이 불가능한 오류 #예외 발생 가능 코드 except <Excetion Type>: #예외 발생시 대응하는 코드
In [3]:# 0으로 숫자를 나눌때 예외처리 for i in range(10): try: print(10/i) except ZeroDivisionError: print(">>>>") print("Not divided by 0") print(">>>>")
>>>> Not divided by 0 >>>> 10.0 5.0 3.3333333333333335 2.5 2.0 1.6666666666666667 1.4285714285714286 1.25 1.1111111111111112
In [8]:a = [0,1,2,3,4] for i in range(10): try: print(i, 10/i) print(a[i]) print(v) except ZeroDivisionError: print(">>>>", "ERROR") print("Not divided by 0") print(">>>>") except IndexError as e: # e : 에러가 어떤것인지 출력하기 위함 print(e) except Exception as e: # 그 외의 에러가 났을때 출력 print(e) # 그러나 다른 사용자가 어디서 에러가 발생했는지 알기가 어려워 좋은 방법은 아님
>>>> ERROR Not divided by 0 >>>> 1 10.0 1 name 'v' is not defined 2 5.0 2 name 'v' is not defined 3 3.3333333333333335 3 name 'v' is not defined 4 2.5 4 name 'v' is not defined 5 2.0 list index out of range 6 1.6666666666666667 list index out of range 7 1.4285714285714286 list index out of range 8 1.25 list index out of range 9 1.1111111111111112 list index out of range
In [13]:# raise : 필요에 따라 강제로 Exception을 발생 while True: value = input("변환할 정수 값을 입력해주세요 ") for digit in value: if digit not in "0123456789": # 정수 값을 넣지 않은 경우 raise ValueError("숫자값을 입력하지 않으셨습니다.") #에러를 미리 발생시켜 필요하지않는 연산을 막음 print("정수값으로 변환된 숫자 -", int(value))
변환할 정수 값을 입력해주세요 a
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-13-e25520171ea5> in <module> 5 for digit in value: 6 if digit not in "0123456789": # 정수 값을 넣지 않은 경우 ----> 7 raise ValueError("숫자값을 입력하지 않으셨습니다.") 8 #에러를 미리 발생시켜 필요하지않는 연산을 막음 9 print("정수값으로 변환된 숫자 -", int(value)) ValueError: 숫자값을 입력하지 않으셨습니다.
In [17]:# assert : 특정 조건에 만족하지 않을 경우 예외 발생 def get_binary_number(decimal_number : int): assert isinstance(decimal_number, int) # True or False 역할로 사용 return bin(decimal_number) print(get_binary_number(10.0))
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) <ipython-input-17-ba0df7c16297> in <module> 5 return bin(decimal_number) 6 ----> 7 print(get_binary_number(10.0)) <ipython-input-17-ba0df7c16297> in get_binary_number(decimal_number) 2 3 def get_binary_number(decimal_number : int): ----> 4 assert isinstance(decimal_number, int) # True or False 역할로 사용 5 return bin(decimal_number) 6 AssertionError:
파일의 종류¶
파일 종류는 text 파일과 binary 파일로 나뉨
- 컴퓨터는 text 파일을 처리하기 위해 binary 파일로 변환시킴
- 모든 text 파일도 실제는 binary 파일, 아스키/유니코드 문자열 집합으로 저장되어 사람이 읽을 수 있음
Python File I/O¶
파이썬은 파일 처리를 위해 "open"키워드를 사용함
In [ ]:f = open("<파일이름>", "접근 모드") # 파일을 읽을 수 있게 주소만 지정
파일열기모드¶
- r : 읽기모드 - 파일을 읽기만 할때 사용
- w : 쓰기모드 - 파일에 내용을 쓸 때 사용
- a : 추가모드 - 파일의 마지막에 새로운 내용을 추가 시킬 때 사용
In [ ]:f = open("i_have_a_dream.txt", "r") contents = f.read() # 대상파일이 같은 폴더에 있을 경우 print(contents) f.close() # 파일을 연것을 닫는다
- With 구문과 함께 사용하기 : With 구문안에 사용하면 들여쓰기 공간동안에 작동하다가 끝나는순간 닫힌다(close).
In [ ]:with open("i_have_a_dream.txt", "r") as my_file: contents = my_file.read() print(type(contents), contents)
한 줄씩 읽어 List Type으로 반환
In [23]:with open("i_have_a_dream.txt", "r") as my_file: content_list = my_file.readlines() # 파일 전체를 list로 반환 print(type(content_list)) # Type 확인 print(content_list) # 리스트 값 출력
<class 'list'> ['Love And Thunder\n', 'Power!']
실행 시 마다 한 줄씩 읽어 오기 : 한번에 메모리에 올리기 힘들경우
In [24]:with open("i_have_a_dream.txt", "r") as my_file: i = 0 while True: line = my_file.readline() # readline : 한줄씩 읽기 if not line: break print(str(i) + "===" + line.replace("\n","")) #한줄씩 값 출력 i = i + 1
0===Love And Thunder 1===Power!
In [1]:with open("i_have_a_dream.txt", "r") as my_file: contents = my_file.read() word_list = contents.split(" ") line_list = contents.split("\n") print("Total Number of Characters :", len(contents)) print("Total Number of Words :", len(word_list)) print("Total Number of lines :", len(line_list))
Total Number of Characters : 23 Total Number of Words : 3 Total Number of lines : 2
In [27]:f = open("count_log.txt", mode='w', encoding="utf8") for i in range(1, 11): data = "{0}번째 줄입니다.\n".format(i) f.write(data) f.close
Out[27]:<function TextIOWrapper.close()>
In [29]:with open("count_log.txt", mode="a", encoding="utf8") as f: # mode="a" 기존파일에 덮어씀 for i in range(11,21): data = "{0}번째 줄입니다.\n".format(i) f.write(data)
OS module¶
os 모듈을 사용해 Directory를 다룰 수 있다.
In [30]:import os os.mkdir("log")
In [35]:try: os.mkdir("abc") except FileExistsError as e: print("Already created")
Already created
In [36]:os.path.exists("abc")
Out[36]:True
In [31]:if not os.path.isdir("log"): # 디렉토리 유무 확인 os.mkdir("log")
In [38]:import shutil # 파일을 옮기는 함수 source = "i_have_a_dream.txt" dest = os.path.join("abc", "dongseok.txt") # 디렉토리 생성 # "abc" + "\\" + "dongseok.txt" : 권장X 이 방식은 윈도우 전용, 리눅스엔 사용X shutil.copy(source, dest) # shutil.copy : 파일 복사 함수
Out[38]:'abc\\dongseok.txt'
pathlib : path를 객체로 다룸, 윈도우와 리눅스 등의 path가 달라도 통일 시킬 수 있음
In [1]:import pathlib
In [2]:pathlib.Path.cwd() # 현재 디렉토리
Out[2]:WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse')
In [3]:cwd = pathlib.Path.cwd() cwd
Out[3]:WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse')
In [4]:cwd.parent # 부모 디렉토리
Out[4]:WindowsPath('C:/Users/dlsef/jupyter project')
In [6]:cwd.parent.parent
Out[6]:WindowsPath('C:/Users/dlsef')
In [7]:list(cwd.parent.parents) # 부모 폴더들을 각각 나눠서 저장
Out[7]:[WindowsPath('C:/Users/dlsef'), WindowsPath('C:/Users'), WindowsPath('C:/')]
In [8]:cwd.glob("*")
Out[8]:<generator object Path.glob at 0x000001A431FAB5C8>
In [9]:list(cwd.glob("*"))
Out[9]:[WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/.ipynb_checkpoints'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/abc'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/count_log.txt'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/fah_converter.py'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/i_have_a_dream.txt'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/log'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/Module and Project'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/module_ex.py'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/Untitled.ipynb'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/Untitled1.ipynb'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/[python]1. Objects_in_Python .ipynb'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/[python]2. Module and Project.ipynb'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/[python]3. Exception_File_LogHandling.ipynb'), WindowsPath('C:/Users/dlsef/jupyter project/naver_boostcorse/__pycache__')]
Log 파일 생성하기¶
In [15]:import os if not os.path.isdir("log"): #log 폴더가 있어요?(isdir 대신 exist도 가능) os.mkdir("log") TARGET_FILE_PATH = os.path.join("log", "count_log.txt") # 로그 디렉토리 설정 if not os.path.exists(TARGET_FILE_PATH): # 처음 log파일 생성 f = open(TARGET_FILE_PATH, 'w', encoding="utf8") f.write("기록이 시작됩니다\n") f.close()
In [16]:with open(TARGET_FILE_PATH, 'a', encoding="utf8") as f: # 추후 추가 import random, datetime for i in range(1, 11): stamp = str(datetime.datetime.now()) value = random.random() * 100000 log_line = stamp + "\n" + str(value) + "값이 생성되었습니다." + "\n" f.write(log_line)
Pickle¶
파이썬의 객체를 영속화(persistence)하는 built-in 객체
객체는 어디에 있어야 하나? 메모리에 업로드, 그러나 파이썬을 종료하면 사라진다. 다시 그 정보를 쓰기 위해선 영속화(파일로 저장) 즉 피클을 사용한다.
- 데이터, object 등 실행중 정보를 저장 -> 불러와서 사용
- 저장해야하는 정보, 계산 결과(모델) 등 활용이 많음
- 파이썬 전용 binary 파일
In [4]:import pickle f = open("list.pickle", "wb") # wb : binary 파일, 메모장에서는 안열린다! test = [1, 2, 3, 4, 5] pickle.dump(test,f) # 저장 f.close()
In [18]:test
Out[18]:[1, 2, 3, 4, 5]
In [19]:del test
In [20]:test
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-20-4e1243bd22c6> in <module> ----> 1 test NameError: name 'test' is not defined
In [21]:f = open("list.pickle", "rb") test_pickle = pickle.load(f) test_pickle f.close()
In [12]:class Multiply(object): def __init__(self, multiplier): self.multiplier = multiplier def multiply(self, number): return number * self.multiplier
In [13]:multiply = Multiply(5) multiply.multiply(5)
Out[13]:25
In [14]:f = open("multiply_object.pickle", "wb") pickle.dump(multiply, f) f.close()
In [15]:del multiply
In [16]:multiply
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-16-d8ca8d133468> in <module> ----> 1 multiply NameError: name 'multiply' is not defined
In [17]:f = open("multiply_object.pickle", "rb") multiply_pickle = pickle.load(f) multiply_pickle.multiply(100)
Out[17]:500
print vs logging¶
기록을 print로 남기는 것도 가능하나, Console 창에만 남기는 기록은 분석시 사용 불가하여 때로는 레벨별(개발, 운영)로 기록을 남길 필요도 있다.
- 모듈별로 별도의 logging을 남길 필요도 있다.
- 이러한 기능을 체계적으로 지원하는 모듈이 필요
logging level¶
프로그램 진행 상황에 따라 다른 Level의 Log를 출력한다.
- 개발 시점(DEBUG), 운영 시점(INFO, WARNING..)마다 다른 Log가 남을 수 있도록 지원, WARNING, ERROR, Critical은 사용자도 볼 수 있다.
- DEBUG < INFO < WARNING < ERROR < Critcal
- Log 관리시 가장 기본이 되는 설정 정보
파이썬에서는 기본적으로 WARNING Level부터 사용자에게 보여진다.
In [18]:import logging # 파이썬의 기본 Log 관리 모듈 logging.debug("틀렸어!!") logging.info("확인!!") logging.warning("조심해!!") logging.error("에러났다!!") logging.critical("망했다!!")
실제 프로그램을 실행할 때는 여러 설정이 필요하다.
1) 데이터 파일 위치 2) 파일 저장 장소 3) Operation Type 등
이와 같은 설정은 두가지 방법이 있다.
- configparser : 파일에 설정
- argparser : 실행시점에
configparser¶
- 프로그램의 실행 설정을 file에 저장함
- Section, Key, Value 값의 형태(Dict 타입)로 설정된 설정 파일을 사용
- 설정파일을 Dict Type으로 호출후 사용
config file¶
[SectionOne]
- Section - 대괄호
Status: Single
- 속성 - Key : Value or Key = Value
Name: Derek
...
In [3]:import configparser config = configparser.ConfigParser() config.sections()
Out[3]:[]
In [4]:config.read("example.cfg") config.sections()
Out[4]:['SectionOne', 'SectionTwo', 'SectionThree']
In [5]:for key in config['SectionOne']: print(key)
status name value age single
In [16]:print(config['SectionOne']) # 객체 형태로만 나타남
<Section: SectionOne>
In [17]:config['SectionOne']
Out[17]:<Section: SectionOne>
In [21]:for key in config['SectionTwo']: value = config['SectionTwo'][key] print("{0} : {1}".format(key,value))
favoritecolor : Green
argparser¶
Console 창에서 프로그램 실행시 Setting 정보를 저장함, 거의 모든 Console 기반 Python 프로그램 기본으로 제공
- 특수 모듈도 많이 존재하지만(TF), 일반적으로 argparse를 사용
- Command-Line Option 이라고 부름
In [22]:import argparse parser = argparse.ArgumentParser(description="Sum Two integers.") parser.add_argument('-a', "--a_value", dest="A_value", help="A integers", type=int) parser.add_argument('-b', "--b_vaule", dest="B_value", help="B integers", type=int) #짧은 이름, 긴이름, 표시명, Help 설명, Argument Type # 실행할때는 -a 10 -b 10 과 같은 방식으로 사전에 입력하여 실행 args = parser.parse_args() print(args) print(args.a) print(args.b) print(args.a + args.b)
usage: ipykernel_launcher.py [-h] [-a A_VALUE] [-b B_VALUE] ipykernel_launcher.py: error: unrecognized arguments: -f C:\Users\dlsef\AppData\Roaming\jupyter\runtime\kernel-794cf7be-8dcb-435c-8107-5336705d73e5.json
An exception has occurred, use %tb to see the full traceback. SystemExit: 2
C:\Users\dlsef\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3339: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
Logging Formatter¶
Log의 결과값의 format을 지정해줄 수 있음
In [23]:formatter = logging.Formatter("%(asctime)s %(levelname)s, %(process)d %(message)s")
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-23-690549970859> in <module> ----> 1 formatter = logging.Formatter("%(asctime)s %(levelname)s, %(process)d %(message)s") NameError: name 'logging' is not defined
In [ ]:logging.config.fileConfig('logging.conf') logger = logging.getLogger()
In [ ]:In [ ]:'인공지능 > 부스트캠프 Ai Tech' 카테고리의 다른 글
[python]5. Numpy (0) 2022.01.21 [python]4. Python Data Handling (0) 2022.01.21 [python]0. Pythonic code (0) 2022.01.21 [python]2. Module and Project (0) 2022.01.21 [python]1. Objects_in_Python (0) 2022.01.21