- pycharm
- 파이썬 시작
- rpm 패키지 확인
- rpm 삭제
- 파이참
- sqlitehandler
- 파이썬
- pycharm 다운
- 파이썬 로깅 모듈
- 데이타베이스 핸들러
- scp 파일보내기
- 파이참 설치
- rpm yum
- scp 리눅스
- 파이썬 초보
- rpm 옵션
- PYTHON
- 로깅모듈 db에 저장
- rpm 설치
- scp 폴더 가져오기
- 리눅스 패키지 확인
- scp 파일 가져오기
- 파이썬 logging 모듈
- 파이썬 설치
- 파이참 다운
- databasehandler
- rpm yum 차이
- 파이썬 logging
- scp 명령어 옵션
- 데이터베이스 핸들러
별과 인간이 그리는 무늬
데이터베이스 핸들러 사용하기(dbhandler, databasehandler, sqlitehandler) | 파이썬 loggining 모듈 본문
데이터베이스 핸들러 사용하기(dbhandler, databasehandler, sqlitehandler) | 파이썬 loggining 모듈
moonui.bee 2021. 2. 4. 21:59무늬비다.
글쓴이의 경우 파이썬을 스크립트를 만들때 기본 모듈인 logging 모듈을 꽤 유용하게 사용하는 편이다.
로깅이 필요한 거의 모든 상황에서 사용한다고 해도 무방할 정도일 듯 싶다.
logging 모듈을 사용할 때 아래에서 소개하는 기본제공되는 핸들러만 사용하여도 대부분 원하는 기능을 구현해낼 수 있다.
StreamHandler
- 인스턴스는 스트림(파일류 객체)에 메시지를 보냅니다.
FileHandler
- 인스턴스는 디스크 파일에 메시지를 보냅니다.
BaseRotatingHandler
- 특정 지점에서 로그 파일을 회전시키는 처리기의 베이스 클래스입니다. 직접 인스턴스화하는 것은 아닙니다.
대신 RotatingFileHandler 또는 TimedRotatingFileHandler 를 사용하십시오.
RotatingFileHandler
- 인스턴스는 디스크 파일에 메시지를 보내는데, 최대 로그 파일 크기와 로그 파일 회전을 지원합니다.
TimedRotatingFileHandler
- 인스턴스는 디스크 파일에 메시지를 보내는데, 일정한 시간 간격으로 로그 파일을 회전시킵니다.
SocketHandler
- 인스턴스는 TCP/IP 소켓에 메시지를 보냅니다. 3.4부터, 유닉스 도메인 소켓도 지원됩니다.
DatagramHandler
- 인스턴스는 UDP 소켓에 메시지를 보냅니다. 3.4부터, 유닉스 도메인 소켓도 지원됩니다.
SMTPHandler
- 인스턴스는 지정된 전자 우편 주소로 메시지를 보냅니다.
SysLogHandler
- 인스턴스는 유닉스 syslog 데몬(원격 기계에 있는 것도 가능합니다)에 메시지를 보냅니다.
NTEventLogHandler
- 인스턴스는 윈도우 NT/2000/XP 이벤트 로그에 메시지를 보냅니다.
MemoryHandler
- 인스턴스는 메모리에 있는 버퍼에 메시지를 보내는데, 특정 기준이 만족 될 때마다 플러시 됩니다.
HTTPHandler
-인스턴스는 GET 또는 POST 을 사용해서 HTTP 서버에 메시지를 보냅니다.
WatchedFileHandler
- 인스턴스는 그들이 로깅하고 있는 파일을 감시합니다. 파일이 변경되면 닫히고 파일 이름을 사용하여 다시 열립니다. 이 처리기는 유닉스 계열 시스템에서만 유용합니다. 윈도우는 사용된 하부 메커니즘을 지원하지 않습니다.
QueueHandler
- 인스턴스는 queue 또는 multiprocessing 모듈에 구현된 것과 같은 큐로 메시지를 보냅니다.
NullHandler
- 인스턴스는 에러 메시지로 아무것도 하지 않습니다. 라이브러리 개발자가 로깅을 사용하지만, 라이브러리 사용자가 로깅을 구성하지 않으면 표시될 수 있는 〈No handlers could be found for logger XXX〉 라는 메시지를 피하려고 할 때 사용합니다. 자세한 정보는 라이브러리 로깅 구성 를 보십시오.
출처: https://docs.python.org/ko/3/howto/logging.html#logging-advanced-tutorial
다만 한가지 아쉬운 점은 데이터베이스에 로그를 저장하는 핸들러는 제공하지 않는다.
그래서 DB에 로그를 저장할 수 있는 DatabaseHandler를 사용하는 방법을 소개해 보려고 한다.
database에는 여러종류가 있지만 설명에 용이하도록 기본으로 제공하는 sqlite3 db를 이용하는 DatabaseHanlder를 제작하도록 하겠다.
step1. 먼저 logging.Handler의 속성을 그대로 상속받는 DatabaseHandler 클랙스를 생성한다.
class DatabaseHandler(logging.Handler):
def __init__(self):
pass
step2. 클래스 초기화 함수(__init__)에 아래와 같은 내용을 정의한다
- 상속받은 logging.hanlder 초기화
- sqlite3 db connect 및 cursor 설정(moonuibee.db 파일 생성)
- db table 생성(log)
class DatabaseHandler(logging.Handler):
def __init__(self):
logging.Handler.__init__(self)
self.database = 'moonuibee.db'
self.conn = sqlite3.connect(self.database)
self.cur = self.conn.cursor()
mk_table_query = '''
CREATE TABLE IF NOT EXISTS log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
insertTime TEXT,
logLv TEXT,
filename TEXT,
lineno INTEGER,
message TEXT
)
'''
self.conn.execute(mk_table_query)
self.conn.commit()
step3. inserTime col에 입력할 시간값을 리턴하는 함수를 정의한다.
logging 모듈에서 시간값은 timestamp형태로 리턴되어
formatter를 이용하여 출력 시 원하는 모양으로 출력되도록 변경할 수 있다.
db에 입력할때는 따로 formatter를 사용하지 않으므로 따로 설정해주도록 한다.
통일성을 해치지 않으려는 습관때문에 record를 입력값으로 사용했으나,
시간값만 리턴할 수 있으면 어느방법으로 메소드를 제작하여도 문제되지 않는다.
def time_format(self, record):
self.now = datetime.datetime.now()
record.nowstr = self.now.strftime('%Y-%m-%d %H:%M:%S')
step4. 이벤트 함수(emit)을 정의한다.
- 트리거가 record 값이므로 반드시 입력값으로 사용
- formatter의 format을 그대로 사용하기 위해 self.format(record) 삽입
- dbtable에 입력
def emit(self, record):
self.format(record)
self.time_format(record)
insert_db_query = '''
INSERT INTO log (
insertTime, logLv, filename, lineno, message) VALUES
('{}', '{}', '{}', {}, '{}')
'''.format(record.nowstr, record.levelname, record.filename, record.lineno, record.message)
self.conn.execute(insert_db_query)
self.conn.commit()
step5. 데이터베이스 connection close
def __del__(self):
try:
self.conn.close()
except:
pass
step1 부터 step5를 모두 합치면 아래와 같다.
import logging, sqlite3, datetime
class DatabaseHandler(logging.Handler):
def __init__(self):
logging.Handler.__init__(self)
self.database = 'moonuibee.db'
self.conn = sqlite3.connect(self.database)
self.cur = self.conn.cursor()
mk_table_query = '''
CREATE TABLE IF NOT EXISTS log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
insertTime TEXT,
logLv TEXT,
filename TEXT,
lineno INTEGER,
message TEXT
)
'''
self.conn.execute(mk_table_query)
self.conn.commit()
def time_format(self, record):
self.now = datetime.datetime.now()
record.nowstr = self.now.strftime('%Y-%m-%d %H:%M:%S')
def emit(self, record):
self.format(record)
self.time_format(record)
insert_db_query = '''
INSERT INTO log (
insertTime, logLv, filename, lineno, message) VALUES
('{}', '{}', '{}', {}, '{}')
'''.format(record.nowstr, record.levelname, record.filename, record.lineno, record.message)
self.conn.execute(insert_db_query)
self.conn.commit()
def __del__(self):
try:
self.conn.close()
except:
pass
사용하는 방법은 로깅모듈에서 핸들러를 추가하는 방법과 정확히 동일하다.
if __name__ == '__main__':
logger = logging.getLogger('moonuibee') # logger name 선언
logger.setLevel(logging.DEBUG) # logger level 설정
sqliteHandler = DatabaseHandler() # database handler 선언
logger.addHandler(sqliteHandler) # database hanlder 추가
logger.debug("debug message") # debug 메세지 작성
logger.info("info message") # info 메세지 작성
logger.warning("warning message") # warning 메세지 작성
logger.critical("critical message") # critical 메세지 작성
수행결과를 moonuibee.db 파일을 sqlite viewer로 열어서 확인해보자
의도한대로 database 테이블에 loggng 메세지가 입력된 것을 확인할 수 있다.
서버에 설치해서 사용하는 db에도 connection 부분만 손보면 그대로 사용할 수 있다.