오늘은 Python으로 로그 파일을 생성하고 log data를 입력하는 class를 만들어 보겠습니다.
이 class는 다른 프로그래밍을 할 때 Log를 기록하는 모듈/패키지로 사용에 유용할 것입니다.
관련 기능
- class
- 예외처리 - try, execpt
- datetime - today(), strftime("%Y%m%d%H%M%S.%f")
- directory 확인 및 생성 - isdir, makedirs
- delay - time.sleep(초)
# LogManager.py
# -*- coding: utf-8 -*-
# Python 3.8.2
# **************************************************************************************
#
# brief Log Manager Class - LogManager(str directory)
#
# file LogManager.py
# date 2020.05.07
# author greensul
#
# **************************************************************************************
from datetime import datetime
import os
import time
class LogManager:
def __init__(self, path):
# Create directory
self.Path = path
try:
if not(os.path.isdir(self.Path)):
os.makedirs(os.path.join(self.Path))
except OSError:
# print(e)
print("[Error] fail to create Log directory : " + self.Path)
except :
print("[Error] create directory - unknown error")
# Create Log File(YYYYMMDD.txt) & log write
def Write(self, data):
self.LogFile = self.Path + '/' + datetime.today().strftime("%Y%m%d") + '.txt'
with open(self.LogFile, "a") as f:
f.write(datetime.today().strftime("%Y%m%d%H%M%S.%f") + "\t" + data + '\n')
if __name__ == '__main__':
print("*****************************************************")
print("* LogManger")
print("*****************************************************")
try:
Log = LogManager("Log")
Log.Write("--[Start LogManager]----------")
for i in range(10):
time.sleep(1)
Log.Write("Done: " + str(i))
Log.Write("--[End Processing]----------")
except Exception as ex:
print("Error : End Processing" , ex)
# Result : 2번 실행
./Log/20200507.txt 파일 내용
20200507221319.243833 --[Start LogManager]----------
20200507221320.244761 Done: 0
20200507221321.246683 Done: 1
20200507221322.252074 Done: 2
20200507221323.255014 Done: 3
20200507221324.256413 Done: 4
20200507221325.258822 Done: 5
20200507221326.268183 Done: 6
20200507221327.279030 Done: 7
20200507221328.284925 Done: 8
20200507221329.286342 Done: 9
20200507221329.287335 --[End Processing]----------
20200507221407.614944 --[Start LogManager]----------
20200507221408.616367 Done: 0
20200507221409.617793 Done: 1
20200507221410.619713 Done: 2
20200507221411.622632 Done: 3
20200507221412.625073 Done: 4
20200507221413.626961 Done: 5
20200507221414.628385 Done: 6
20200507221415.630850 Done: 7
20200507221416.632725 Done: 8
20200507221417.635141 Done: 9
20200507221417.636127 --[End Processing]----------
# 설명
상단에는 파일 정보 및 python 버전을 기록합니다.
class LogManager:
- LogManager 이름으로 Class를 생성합니다.
def __init__(self, path):
self.Path = path
- class의 인스턴스를 만들 때(Class를 호출할 때) 자동으로 def __init__(self)이라는 특수 method를 호출합니다.
이 method는 arguments을 가질 수 있습니다.
log 파일을 저장할 directory를 path라는 arg로 입력받았습니다.
path는 self.Path 에 저장합니다.
Log = LogManager("Log")
- class 인스턴스인 Log를 만들었으며 이때 "Log" 경로를 argument로 호출합니다.
try:
if not(os.path.isdir(self.Path)):
os.makedirs(os.path.join(self.Path))
except OSError:
self.Path = "[Error] fail to create directory : " + self.Path
self.Path = ""
except :
print("[Error] create directory - unknown error")
- try , except 으로 예외 처리를 하였습니다. 폴더를 생성하다 실패하는 경우 에러 메시지를 출력합니다.
테스트 방법은 마지막에 설명드리겠습니다. Python 도 다른 프로그램과 마찬가지로 예외 처리가 중요합니다.
이를 통해 프로그램의 완성도가 올라간다고 볼 수 있습니다.
다른 에러 메시지는 로그 파일에 기록하겠으나 OSError 발생할 경우 Log 폴더 자체를 생성 못했을 것이기에 에러 메시지를 출력하기만 합니다.
def Write(self, data):
self.LogFile = self.Path + '/' + datetime.today().strftime("%Y%m%d") + '.txt'
with open(self.LogFile, "a") as f:
f.write(datetime.today().strftime("%Y%m%d%H%M%S.%f") + "\t" + data + '\n')
- Wirte 함수를 정의합니다.
해당 함수는 data를 받아 Log File에 로그를 기록합니다.
로그 파일명을 연월일. txt 형태로 생성합니다. datetime 모듈의 datetime class를 사용합니다.
로그 파일을 with로 open 합니다. 이는 with 블록을 벗어나면 파일 객체(f)가 자동으로 close 됩니다.
년월일시분초.마이크로초로 로그 발생 시점을 기록한 후 Tab("\t") 이후 인자로 받은 data 기록합니다.
개행 문자("\n")를 사용하여 줄 바꿈을 진행합니다.
strftime("%Y%m%d%H%M%S.%f") - YYYYmmddHHMMSS.ffffff 의 포맷으로 변환합니다.
.%f 를 추가하여 마이크로초 단위까지 기록합니다.
좀 더 자세한 옵션들은 아래 링크에서 "strftime() and strptime() Behavior"를 참고 부탁드립니다.
https://docs.python.org/3.8/library/datetime.html#strftime-and-strptime-behavior
from datetime import datetime
import os
import time
- os 모듈은 디렉터리 관련하여, time은 딜레이 함수 sleep(second)를 위해 import 하였습니다.
from ... import ... 는 datetime 모듈의 datetime class만 가져옵니다. os, time 과는 class를 명시(import 뒤의 datetime)한 차이가 있습니다.
이는 datetime의 다른 class (ex. time, timezone..) 은 사용을 못합니다. 또한 class를 명시할 경우 datetime.datetime
를 datetime으로 사용합니다. 만약 import datetime으로 모듈만 가져올 경우 datetime.datetime.today().strftime('...') 로 호출해야 합니다.
try:
Log = LogManager("Log")
Log.Write("--[Start LogManager]----------")
for i in range(10):
time.sleep(1)
Log.Write("Done: " + str(i))
Log.Write("--[End Processing]----------")
except Exception as ex:
print("Error : End Processing" , ex)
- 예외 처리를 합니다. 예외 발생 시 프로그램을 종료하고 오류 메시지를 출력합니다.
Log.Write("--[Start LogManager]----------") 을 통해 LogManager class 의 Write 함수를 호출합니다.
Write 함수는 해당 data("--[Start LogManager]----------")를 로그 파일에 기록합니다.
for 문을 통해 중간 과정의 로그를 기록하는 sample 을 만들어 보았습니다.(time 모듈을 사용할 필요가 없기 때문에 실제 사용 시에는 해당 for 문과 import time 을 삭제하시는 것이 좋습니다.)
1초 간격으로 로그를 기록합니다(Done: 0 ~ 9 까지 10개 로그 생성)
마지막으로 프로그램이 정상 종료되었기 때문에 로그를 기록합니다.
except Exception을 통해 예외 처리를 합니다. 이는 구동 중에 발생하는 모든 에러에 대해 예외 처리하고 에러 메시지를 출력해 줍니다.
예외 처리 테스트를 위해 Log 폴더를 삭제하고 log 파일을 만들어 보겠습니다.
새로 만들기를 통해 txt 문서를 생성하고 filename을 log로 바꿔줍니다. 확장자. txt는 삭제합니다.
LogManager.py를 실행합니다.
*****************************************************
* LogManger
*****************************************************
[Error] fail to create Log directory : Log
Error : End Processing [Errno 2] No such file or directory: 'Log/20200507.txt'
Log 폴더를 만들어야 하나 이미 동일 이름의 파일이 존재하므로 LogManager Class의 init 에서 첫 번째 에러가 발생합니다. 그 이후 로그를 기록하기 위해 호출한 Log.Write("--[Start LogManager]----------")에서 Log 폴더의 로그 파일을 없기 때문에 두 번째 에러가 발생하며 프로그램이 종료됩니다.
지금까지 Log 를 관리하는 LogManager 를 통해 class 를 생성하며 관련된 기능들을 알아보았습니다.
이를 다른 프로그램의 모듈(패키지)로 사용하면 일관성 있는 로그 파일을 생성할 수 있을 것입니다.
코딩을 하면서 글을 작성하니 시간이 많이 걸리네요.
빨리 익숙해지면 좋겠습니다~
'IT > Python' 카테고리의 다른 글
[Python] Gmail 을 이용하여 메일 발송 시 Error 처리 - Gmail 앱 비밀번호 설정 (0) | 2020.05.15 |
---|---|
[Python] E-Mail Send - Email Bomber Test (0) | 2020.05.14 |
[Python] 구구단 프로그래밍 예제 (0) | 2020.05.05 |
[Python] 자료형 - 문자열(String) (0) | 2020.05.04 |
[Python] 자료형 - 숫자형과 연산자를 이용한 계산 (0) | 2020.05.02 |
댓글