MainApp.py 에서 사용했던 logger이다. logging 모듈을 사용했고 텔레그램, 디버깅파일, 로그파일, 콘솔출력 총 4가지를 사용한다.
#logger print info message
@singleton
class Telog():
def __init__(self):
self.logger = logging.getLogger("AppInfoText")
self.logger.setLevel(logging.DEBUG)
Telog라는 클래스를 만들어준다. 여기서 텔레그램, 디버깅파일, 로그파일, 콘솔출력 4가지를 동시에 진행할것이다.
Logger의 이름은 AppInfoText라고 지어줬고 디버그파일을 출력하기위해 Level을 logging.DEBUG로 설정해주었다.
또한 동시에 여러파일에서 사용되기 때문에 중복생성을 방지하기위해 싱글톤형식으로 만들어주었다.
#set debugging file handler
debugformat = '[%(asctime)s|{}|%(levelname)s|%(filename)s:%(funcName)s:%(lineno)s] %(message)s'. \
format(self.logger.name)
debugformatter = logging.Formatter(debugformat)
debug_log_path = datetime.now().strftime("debug/Debugger %Y-%m-%d %H-%M-%S.log")
debug_handler = logging.FileHandler(filename = debug_log_path, encoding="utf-8")
debug_handler.setFormatter(debugformatter)
debug_handler.setLevel(logging.DEBUG)
디버그파일을 만드는 코드. 대충 format을 설정해주었고 파일명은 다음과 같이 작성해주었다.
그렇게 handler를 만들어서 적용해주었고, 디버그내용을 표시하기 위해 Level을 Debug로 설정했다.
#set file handler
fileformat = '[%(asctime)s|{}|%(levelname)s|%(filename)s:%(funcName)s:%(lineno)s] %(message)s'. \
format(self.logger.name)
fileformatter = logging.Formatter(fileformat)
file_log_path = datetime.now().strftime("log/AppLog %Y-%m-%d.log")
file_handler = logging.FileHandler(filename = file_log_path, encoding="utf-8")
file_handler.setFormatter(fileformatter)
file_handler.setLevel(logging.INFO)
두번째로 로그를 출력해줄 파일 핸들러를 만들어주었다. 아까와 같은 형식이지만 파일명을 로그 폴더안에 날짜만 출력되도록 하였다.
개발은 해당 날짜에 한번만 실행되도록 만들었기때문에 어차피 로그가 하루에 하나 뿐이지만, 디버깅을 해본 결과 같은날짜에 두번 이상 프로그램을 실행했다면, 해당로그파일 밑에 이어서 작성이 된다.
로그를 찍어주는 파일이기 때문에 Level을 INFO로 설정해주었다.
(위의 종목은 테스트용으로 임의의 종목을 선택한 것이므로 실제 매매와 전혀 관련없는 종목이다)
#set console handler
streamformat='%(asctime)s [%(levelname)s] %(message)s - %(filename)s:%(lineno)d'
streamformatter = logging.Formatter(streamformat)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(streamformatter)
stream_handler.setLevel(logging.DEBUG) #for test
콘솔의 출력을 관리해주는 핸들러다. Formatter는 조금 더 보기 쉽게 파일과 다른 형식을 사용하였다.
테스트를 위해 Level을 Debug로 설정해주었다.
마지막으로 텔레그램 출력을 위한 핸들러를 만들어주어야한다.
import telegram
#telegram handler
class LogTelHandler(logging.Handler):
def __init__(self, *args, **kwargs):
super().__init__()
self.telbot = telegram.Bot(token=keyManager.getJsonData("telegram_token"))
self.chatid = keyManager.getJsonData("telegram_chatid")
def emit(self, record):
if self.formatter is None:
text = record.msg
else:
text = self.formatter.format(record)
self.telbot.sendMessage(chat_id=self.chatid, text=text)
텔레그램 모듈은 python-telegram-bot 모듈을 사용하였다.
https://github.com/python-telegram-bot/python-telegram-bot
GitHub - python-telegram-bot/python-telegram-bot: We have made you a wrapper you can't refuse
We have made you a wrapper you can't refuse. Contribute to python-telegram-bot/python-telegram-bot development by creating an account on GitHub.
github.com
init 함수에선 keyManager파일에서 관리하는 json 파일에 저장해둔 telegram 토큰과 chatid를 가져온다.
handler내에선 실제 logging을 처리하기 위해 emit이라는 함수를 사용한다. emit함수 내에서 실제 봇이 메시지를 보내도록 설정해준다.
#set telegram handler
telformat= datetime.now().strftime("[%m/%d %H:%M:%S.%f] ") + '%(message)s'
telformatter = logging.Formatter(telformat)
telegram_handler = LogTelHandler()
telegram_handler.setFormatter(telformatter)
telegram_handler.setLevel(logging.INFO)
다시 Telog의 init으로 돌아와서, 위와 같이 설정해주었다.
텔레그램은 모바일로 주로 보기때문에 Formatter을 조금 더 간결하게 만들어 주었다.
이제 위에서 만든 4개의 handler을 전부 logger에 추가를 해주어야한다.
# Add Formatters
self.logger.addHandler(stream_handler)
self.logger.addHandler(telegram_handler)
self.logger.addHandler(file_handler)
self.logger.addHandler(debug_handler)
추가로 위와같이 관리를 하니 실제 거래내역만 보기에는 어렵다는 생각이 들었다. 그래서 따로 거래내역만 저장해주는 logger를 추가로 만들어주었다.
#거래 로그
@singleton
class TradeLog():
def __init__(self):
self.logger = logging.getLogger("TradeLog")
self.logger.setLevel(logging.INFO)
#set file handler
fileformat = '[%(asctime)s] %(message)s'
fileformatter = logging.Formatter(fileformat)\
file_log_path = datetime.now().strftime("log/TradeLog %Y-%m-%d.log")
file_handler = logging.FileHandler(filename = file_log_path, encoding="utf-8")
file_handler.setFormatter(fileformatter)
file_handler.setLevel(logging.INFO)
# Add Formatters
self.logger.addHandler(file_handler)
위의 로그파일 사진과 같이 TradeLog파일로 출력되며 종목 정보만 출력해주도록 사용을 할 예정이다.
아래는 telog.py의 전체코드이다.
import logging
import telegram
from singleton_decorator import singleton
from datetime import datetime
from mydata import keyManager
"""
logging.basicConfig(
format='%(asctime)s [%(levelname)s] %(message)s - %(filename)s:%(lineno)d',
level=logging.DEBUG)
"""
#logger print info message
@singleton
class Telog():
def __init__(self):
self.logger = logging.getLogger("AppInfoText")
self.logger.setLevel(logging.DEBUG)
#set debugging file handler
debugformat = '[%(asctime)s|{}|%(levelname)s|%(filename)s:%(funcName)s:%(lineno)s] %(message)s'. \
format(self.logger.name)
debugformatter = logging.Formatter(debugformat)
debug_log_path = datetime.now().strftime("debug/Debugger %Y-%m-%d %H-%M-%S.log")
debug_handler = logging.FileHandler(filename = debug_log_path, encoding="utf-8")
debug_handler.setFormatter(debugformatter)
debug_handler.setLevel(logging.DEBUG)
#set file handler
fileformat = '[%(asctime)s|{}|%(levelname)s|%(filename)s:%(funcName)s:%(lineno)s] %(message)s'. \
format(self.logger.name)
fileformatter = logging.Formatter(fileformat)
file_log_path = datetime.now().strftime("log/AppLog %Y-%m-%d.log")
file_handler = logging.FileHandler(filename = file_log_path, encoding="utf-8")
file_handler.setFormatter(fileformatter)
file_handler.setLevel(logging.INFO)
#set console handler
streamformat='%(asctime)s [%(levelname)s] %(message)s - %(filename)s:%(lineno)d'
streamformatter = logging.Formatter(streamformat)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(streamformatter)
stream_handler.setLevel(logging.DEBUG) #for test
#set telegram handler
telformat= datetime.now().strftime("[%m/%d %H:%M:%S.%f] ") + '%(message)s'
telformatter = logging.Formatter(telformat)
telegram_handler = LogTelHandler()
telegram_handler.setFormatter(telformatter)
telegram_handler.setLevel(logging.INFO)
# Add Formatters
self.logger.addHandler(stream_handler)
self.logger.addHandler(telegram_handler)
self.logger.addHandler(file_handler)
self.logger.addHandler(debug_handler)
#telegram handler
class LogTelHandler(logging.Handler):
def __init__(self, *args, **kwargs):
super().__init__()
self.telbot = telegram.Bot(token=keyManager.getJsonData("telegram_token"))
self.chatid = keyManager.getJsonData("telegram_chatid")
def emit(self, record):
if self.formatter is None:
text = record.msg
else:
text = self.formatter.format(record)
self.telbot.sendMessage(chat_id=self.chatid, text=text)
#거래 로그
@singleton
class TradeLog():
def __init__(self):
self.logger = logging.getLogger("TradeLog")
self.logger.setLevel(logging.INFO)
#set file handler
fileformat = '[%(asctime)s] %(message)s'
fileformatter = logging.Formatter(fileformat)
file_log_path = datetime.now().strftime("log/TradeLog %Y-%m-%d.log")
file_handler = logging.FileHandler(filename = file_log_path, encoding="utf-8")
file_handler.setFormatter(fileformatter)
file_handler.setLevel(logging.INFO)
# Add Formatters
self.logger.addHandler(file_handler)
telog.py
'개발 > 주식 자동매매 (파이썬)' 카테고리의 다른 글
[Python] 주식 자동매매 프로그램 만들기 1. MainApp 클래스 init (0) | 2021.08.13 |
---|---|
주식 자동매매 (파이썬) (0) | 2021.08.13 |