-
Debugクラスを作成して__init__(), __str__()メソッドを追加する
ここではDebugクラスを作成して__init__()と__str__()メソッドを追加します。
行8ではWindows用のサウンドライブラリを取り込んでいます。
行13ではBcolorsクラス、Gvarクラスを取り込んでいます。
行27-29では__init__()メソッドを定義しています。
__init__()メソッドは、Debugクラスのインスタンスを生成したときに自動的に呼ばれます。
Debugクラスのインスタンスを生成するときは、引数にGvarのオブジェクトを指定します。
行28ではgvarプロパティ(Pythonでは属性と呼ぶ)にGvarのオブジェクトを設定しています。
行29ではfolder_gmoプロパティにBOTのフォルダ名を設定します。
フォルダ名はGvarクラスのdomainとexchangeプロパティから取得して生成します。
行31-32では__str__()メソッドを定義しています。
このメソッドではDebugクラスからgvarとfolder_gmoのプロパティを取得して返します。
__str__()メソッドはDebugクラスをprint()等で参照したときに自動的に呼ばれます。
__str__()メソッドの詳しいことは、
「記事(Article087)」で解説しています。
debug.py:
# debug.py
"""
Debug class
"""
### import the libraries
import winsound
from time import sleep
import datetime as dt
from lib.base import Bcolors, Gvar
import warnings
warnings.simplefilter('ignore')
############ Debug class
class Debug:
"""
__init__(self, gvar)
print_log()
trace_write(), trace_warn(), trace_error()
sound_alert()
"""
def __init__(self, gvar: object) -> None:
self.gvar = gvar
self.folder_gmo = f'{self.gvar.domain}/{self.gvar.exchange}/' # desktop-pc/bot/
def __str__(self) -> str:
return f"Debug({self.gvar=}, {self.folder_gmo=})"
図1ではDebugクラスのプロパティを表示しています。
-
Debugクラスにprint_log()メソッドを追加する
ここではDebugクラスにprint_log()メソッドを追加しています。
このメソッドはGvarクラスのdebug_modeプロパティが「True/False」いずれのときでも画面とログファイルにを出力します。
行6-8ではログファイルのファイル名を生成しています。
ファイル名は「log(yyyymmdd).txt」になります。
「yyyymmdd」は当日のシステム日付になります。
行11-20ではテキスト文字からエスケープシーケンス(ESC)を除去しています。
行23-31ではテキスト文字をログファイルに出力しています。
行34-37ではテキスト文字を画面に表示しています。
テキスト文字には当日の「日時」が追加されます。
debug.py:
###############################################
def print_log(self, msg: str, msg2=any) ->None:
msg = str(msg) # cast string
# write log to a txt file
now = dt.datetime.now() # current date and time
date_str = now.strftime('%Y%m%d') # 20220924
txt_file = self.folder_gmo + f'log({date_str}).txt' # desktop-pc/bot/log(20220924).txt
# remove ESC
log_msg = msg.replace(Bcolors.HEADER,'').replace(Bcolors.OKBLUE,'').replace(Bcolors.OKCYAN,'')
log_msg = log_msg.replace(Bcolors.OKGREEN,'').replace(Bcolors.WARNING,'').replace(Bcolors.FAIL,'')
log_msg = log_msg.replace(Bcolors.ENDC,'').replace(Bcolors.BOLD,'').replace(Bcolors.UNDERLINE,'')
# remoce ESC
if msg2 != any:
msg2 = str(msg2) # cast msg2
log_msg2 = msg2.replace(Bcolors.HEADER,'').replace(Bcolors.OKBLUE,'').replace(Bcolors.OKCYAN,'')
log_msg2 = log_msg2.replace(Bcolors.OKGREEN,'').replace(Bcolors.WARNING,'').replace(Bcolors.FAIL,'')
log_msg2 = log_msg2.replace(Bcolors.ENDC,'').replace(Bcolors.BOLD,'').replace(Bcolors.UNDERLINE,'')
# append a msg, msg2 into the log file => log(YYYYMMDD).txt
f = open(txt_file, 'a', encoding='utf-8')
f.write(log_msg)
if msg2 != any:
f.write(', ' + log_msg2)
f.write(f" [{now.strftime('%Y-%m-%d %H:%M:%S')}]")
f.write('\n')
f.close()
# print a msg, msg2 to the screen
if msg2 == any:
print(msg, f"[{Bcolors.OKCYAN}{now.strftime('%Y-%m-%d %H:%M:%S')}{Bcolors.ENDC}]")
else:
print(msg, msg2, f"[{Bcolors.OKCYAN}{now.strftime('%Y-%m-%d %H:%M:%S')}{Bcolors.ENDC}]")
図2-1はデモプログラムの実行結果です。
Gvarクラスのdebug_modeプロパティが「True/False」いずれの場合も画面に表示されています。
図2-2はログファイルの内容です。
-
Debugクラスにtrace_write(), trace_warn(), trace_error()メソッドを追加する
ここではDebugクラスにtrace系の3種類のメソッドを追加しています。
trace系のメソッドはGvarクラスのdebug_modeプロパティが「True」の場合のみ画面とログファイルに出力します。
trace_write()は白色、trace_warn()は黄色、trace_error()は赤色で表示します。
BOTで仮想トレードするときは、
Gvarクラスを「debug_mode=True」にしてDebugクラスのtrace系のメソッドでパラメータを調整するためのさまざまな情報を表示させます。
そして、リアルトレードするときは「debug_mode=False」にして必要最小限の情報のみ表示させます。
debug.py:
########################################
def trace_write(self, msg: str) -> None:
if self.gvar.debug_mode: self.print_log(msg)
#######################################
def trace_warn(self, msg: str) -> None:
if self.gvar.debug_mode: self.print_log(f'{Bcolors.WARNING}{msg}{Bcolors.ENDC}')
########################################
def trace_error(self, msg: str) -> None:
if self.gvar.debug_mode: self.print_log(f'{Bcolors.FAIL}{msg}{Bcolors.ENDC}')
図3-1は実行結果です。
trace系のメソッドは、Gvarクラスのdebug_modeプロパティが「True」のときのみ表示されています。
図3-2はログファイルの内容です。
-
Debugクラスにsound_alert()メソッドを追加する
ここではDebugクラスにsound_alert()メソッドを追加します。
このメソッドは引数で指定した回数分警告音を鳴らします。
行4の周波数(単位:ヘルツ)を変更すると音を変えることができます。
各自のお好みの音にカスタマイズしてください。
行5-7のforループでは、指定した回数だけ警告音を0.5秒間隔で鳴らします。
sound_alert()は、仮想通貨の注文が約定したり、BOTで深刻なエラー等が発生したときに使うと便利です。
debug.py:
#######################################
def sound_alert(self, count=1) -> None:
duration = 1000 # milliseconds
freq = 440 # Hz
for i in range(count):
winsound.Beep(freq, duration)
sleep(0.5)
図4-1は実行結果です。
ここでは警告音を1回鳴らして3秒スリープし、
次に警告音を3回鳴らして3秒スリープし、
最後に警告音を5回鳴らしています。
図4-2はWindows 11のレコーダで録音した画像です。
Audioの再生ボタンをクリックすると実際の警告音を聴くことができます。
-
Debugクラスのすべてを掲載
# debug.py
"""
Debug class
"""
### import the libraries
import winsound
from time import sleep
import datetime as dt
from lib.base import Bcolors, Gvar
import warnings
warnings.simplefilter('ignore')
############ Debug class
class Debug:
"""
__init__(self), __init__(self, gvar)
print_log()
trace_write(), trace_warn(), trace_error()
sound_alert()
"""
#########################################
def __init__(self, gvar: object) -> None:
self.gvar = gvar
self.folder_gmo = f'{self.gvar.domain}/{self.gvar.exchange}/' # desktop-pc/bot/
#########################
def __str__(self) -> str:
return f"Debug({self.gvar=}, {self.folder_gmo=})"
###############################################
def print_log(self, msg: str, msg2=any) ->None:
msg = str(msg) # cast string
# write log to a txt file
now = dt.datetime.now() # current date and time
date_str = now.strftime('%Y%m%d') # 20220912
txt_file = self.folder_gmo + f'log({date_str}).txt' # desktop-pc/bot/log(20220912).txt
# remove ESC
log_msg = msg.replace(Bcolors.HEADER,'').replace(Bcolors.OKBLUE,'').replace(Bcolors.OKCYAN,'')
log_msg = log_msg.replace(Bcolors.OKGREEN,'').replace(Bcolors.WARNING,'').replace(Bcolors.FAIL,'')
log_msg = log_msg.replace(Bcolors.ENDC,'').replace(Bcolors.BOLD,'').replace(Bcolors.UNDERLINE,'')
# remoce ESC
if msg2 != any:
msg2 = str(msg2) # cast msg2
log_msg2 = msg2.replace(Bcolors.HEADER,'').replace(Bcolors.OKBLUE,'').replace(Bcolors.OKCYAN,'')
log_msg2 = log_msg2.replace(Bcolors.OKGREEN,'').replace(Bcolors.WARNING,'').replace(Bcolors.FAIL,'')
log_msg2 = log_msg2.replace(Bcolors.ENDC,'').replace(Bcolors.BOLD,'').replace(Bcolors.UNDERLINE,'')
# append a msg, msg2 into the log file => log(YYYYMMDD).txt
f = open(txt_file, 'a', encoding='utf-8')
f.write(log_msg)
if msg2 != any:
f.write(', ' + log_msg2)
f.write(f" [{now.strftime('%Y-%m-%d %H:%M:%S')}]")
f.write('\n')
f.close()
# print a msg, msg2 to the screen
if msg2 == any:
print(msg, f"[{Bcolors.OKCYAN}{now.strftime('%Y-%m-%d %H:%M:%S')}{Bcolors.ENDC}]")
else:
print(msg, msg2, f"[{Bcolors.OKCYAN}{now.strftime('%Y-%m-%d %H:%M:%S')}{Bcolors.ENDC}]")
########################################
def trace_write(self, msg: str) -> None:
if self.gvar.debug_mode: self.print_log(msg)
#######################################
def trace_warn(self, msg: str) -> None:
if self.gvar.debug_mode: self.print_log(f'{Bcolors.WARNING}{msg}{Bcolors.ENDC}')
########################################
def trace_error(self, msg: str) -> None:
if self.gvar.debug_mode: self.print_log(f'{Bcolors.FAIL}{msg}{Bcolors.ENDC}')
#######################################
def sound_alert(self, count=1) -> None:
duration = 1000 # milliseconds
freq = 440 # Hz
for i in range(count):
winsound.Beep(freq, duration)
sleep(0.5)