继续完善logger
This commit is contained in:
parent
029fdb1f47
commit
fc734a62cb
@ -14,7 +14,6 @@ gitee: @shenjackyuanjie
|
|||||||
# 单独导入的(或者就这一个有用的)
|
# 单独导入的(或者就这一个有用的)
|
||||||
from .delivery import Delivery
|
from .delivery import Delivery
|
||||||
|
|
||||||
# lazy之后之前全部导入的(太多了写不动__all__了)
|
# lazy之后之前全部导入的(太多了写不动__all__了
|
||||||
from .calculation import *
|
|
||||||
from .scientific_unit import *
|
from .scientific_unit import *
|
||||||
|
|
||||||
|
@ -1,307 +0,0 @@
|
|||||||
# -------------------------------
|
|
||||||
# Difficult Rocket
|
|
||||||
# Copyright © 2021-2022 by shenjackyuanjie 3695888@qq.com
|
|
||||||
# All rights reserved
|
|
||||||
# -------------------------------
|
|
||||||
|
|
||||||
"""
|
|
||||||
writen by shenjackyuanjie
|
|
||||||
mail: 3695888@qq.com
|
|
||||||
github: @shenjackyuanjie
|
|
||||||
gitee: @shenjackyuanjie
|
|
||||||
"""
|
|
||||||
|
|
||||||
import math
|
|
||||||
import decimal
|
|
||||||
|
|
||||||
from typing import List, Optional, Union
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
|
|
||||||
# linear_algebra
|
|
||||||
|
|
||||||
|
|
||||||
def C_R_P(position: List, degrees: List): # stand for calculation
|
|
||||||
"""
|
|
||||||
very thanks for lenny from pyglet developer
|
|
||||||
https://github.com/LennyPhoenix
|
|
||||||
this part of code is write by him
|
|
||||||
"""
|
|
||||||
radians = degrees * (math.pi / 180)
|
|
||||||
cos = math.cos(radians)
|
|
||||||
sin = math.sin(radians)
|
|
||||||
rotated_pos = (position[0] * cos - position[1] * sin, position[0] * sin + position[1] * cos)
|
|
||||||
return rotated_pos
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
Physics calculation
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def is_decimal(A: any) -> bool:
|
|
||||||
if isinstance(A, decimal.Decimal):
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def F_D(A: decimal, B: decimal) -> decimal:
|
|
||||||
if is_decimal(A) and is_decimal(B):
|
|
||||||
return A / B
|
|
||||||
|
|
||||||
|
|
||||||
def F_Mu(A: decimal, B: decimal) -> decimal:
|
|
||||||
if is_decimal(A) and is_decimal(B):
|
|
||||||
return A * B
|
|
||||||
|
|
||||||
|
|
||||||
def F_Mi(A: decimal, B: decimal) -> decimal:
|
|
||||||
if is_decimal(A) and is_decimal(B):
|
|
||||||
return A - B
|
|
||||||
|
|
||||||
|
|
||||||
def F_A(A: decimal, B: decimal) -> decimal:
|
|
||||||
if is_decimal(A) and is_decimal(B):
|
|
||||||
return A + B
|
|
||||||
|
|
||||||
|
|
||||||
def D_C(listA: list, listB: list): # stand for Duplicate check
|
|
||||||
"""
|
|
||||||
usage:\n
|
|
||||||
input two list\n
|
|
||||||
the fun will do duplicate check and sort then\n
|
|
||||||
the fun won't return any thing just change the list now
|
|
||||||
"""
|
|
||||||
for unit in listB:
|
|
||||||
if unit in listA:
|
|
||||||
listA.remove(unit)
|
|
||||||
listB.remove(unit)
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
listA.sort()
|
|
||||||
listB.sort()
|
|
||||||
|
|
||||||
|
|
||||||
def S_C_float_check(SC): # stand for Scientific notation's float check
|
|
||||||
"""
|
|
||||||
formats:
|
|
||||||
SC list format:docs.basic_config.json:basic_number"""
|
|
||||||
while SC[0] >= 10:
|
|
||||||
SC[0] = F_D(SC[0], 10)
|
|
||||||
SC[1] += 1
|
|
||||||
while SC[0] < 1:
|
|
||||||
SC[0] = F_Mu(SC[0], 10)
|
|
||||||
SC[1] -= 1
|
|
||||||
|
|
||||||
|
|
||||||
def S_N_M(*SN): # stand for Scientific notation multiple
|
|
||||||
"""
|
|
||||||
formats:
|
|
||||||
A & B & C list format:docs.basic_config.json:basic_number"""
|
|
||||||
if len(SN) < 2:
|
|
||||||
raise TypeError('it need more than 1!')
|
|
||||||
elif len(SN) == 2:
|
|
||||||
return __S_N_M(SN[0], SN[1])
|
|
||||||
else:
|
|
||||||
R = __S_N_M(SN[0], SN[1])
|
|
||||||
for A in SN[2:]:
|
|
||||||
R = __S_N_M(R, A)
|
|
||||||
return R
|
|
||||||
|
|
||||||
|
|
||||||
def __S_N_M(A, B):
|
|
||||||
"""
|
|
||||||
formats:
|
|
||||||
A & B list format:docs.basic_config.json:basic_number"""
|
|
||||||
R = [F_Mu(A[0], B[0]), A[1] + B[1]]
|
|
||||||
S_C_float_check(R)
|
|
||||||
Unit1, Unit2 = A[2] + B[2], A[3] + B[3]
|
|
||||||
if Unit1 is None:
|
|
||||||
Unit1 = []
|
|
||||||
D_C(Unit1, Unit2)
|
|
||||||
R += [Unit1, Unit2]
|
|
||||||
return R
|
|
||||||
|
|
||||||
|
|
||||||
def S_N_D(A, B): # stand for Scientific notation divided
|
|
||||||
"""
|
|
||||||
formats:
|
|
||||||
A & B list format:docs.basic_config:basic_number"""
|
|
||||||
R = [F_D(A[0], B[0]), A[1] - B[1]]
|
|
||||||
S_C_float_check(R)
|
|
||||||
Unit1, Unit2 = A[2] + B[3], A[3] + B[2]
|
|
||||||
if Unit1 is None:
|
|
||||||
Unit1 = []
|
|
||||||
D_C(Unit1, Unit2)
|
|
||||||
R += [Unit1, Unit2]
|
|
||||||
return R
|
|
||||||
|
|
||||||
|
|
||||||
def G_C(M, m, R, G): # stand for gravity calculation
|
|
||||||
"""
|
|
||||||
formats:
|
|
||||||
M : ship's mass
|
|
||||||
m : planet's mass
|
|
||||||
R : distance to the planet
|
|
||||||
G : Gravitational constant
|
|
||||||
M & m & R format: docs.basic_config:basic_number
|
|
||||||
"""
|
|
||||||
g = basic_force()
|
|
||||||
A = S_N_M(M, m, G)
|
|
||||||
g = S_N_D(A, S_N_M(R, R))
|
|
||||||
return g
|
|
||||||
|
|
||||||
|
|
||||||
def distance(A, B):
|
|
||||||
"""
|
|
||||||
formats:
|
|
||||||
A & B format: docs.basic_config:basic_poi
|
|
||||||
"""
|
|
||||||
poi_dis = basic_poi()
|
|
||||||
for x in A, B:
|
|
||||||
x = decimal.Decimal(str(x))
|
|
||||||
xd = A[0] - B[0]
|
|
||||||
yd = A[1] - B[1]
|
|
||||||
poi_dis[0] = xd
|
|
||||||
poi_dis[1] = yd
|
|
||||||
# 勾股定理
|
|
||||||
poi_dis[0] **= 2
|
|
||||||
poi_dis[1] **= 2
|
|
||||||
poi_dis.append(poi_dis[0] + poi_dis[1])
|
|
||||||
poi_dis[2] **= 0.5
|
|
||||||
return poi_dis[2]
|
|
||||||
|
|
||||||
|
|
||||||
def _BasicNumber(int_num=0, float_num=1, unit1=None, unit2=None) -> list:
|
|
||||||
if unit1 is None:
|
|
||||||
unit1 = []
|
|
||||||
if unit2 is None:
|
|
||||||
unit2 = []
|
|
||||||
if is_decimal(float_num): # is decimal class?
|
|
||||||
return [int_num, float_num, unit1, unit2] # is just return
|
|
||||||
else:
|
|
||||||
return [int_num, decimal.Decimal(str(float_num)), unit1, unit2] # no create a decimal class
|
|
||||||
|
|
||||||
|
|
||||||
def BasicNumber(int_num=0, float_num=1, unit1=None, unit2=None, num=1) -> list:
|
|
||||||
numbers = []
|
|
||||||
if num > 1:
|
|
||||||
for x in range(0, num, 1):
|
|
||||||
numbers.append(_BasicNumber(int_num, float_num, unit1, unit2))
|
|
||||||
elif num == 1:
|
|
||||||
return _BasicNumber(int_num, float_num, unit1, unit2)
|
|
||||||
else: # num < 1
|
|
||||||
raise TypeError('you should give me a num with >= 1!')
|
|
||||||
return numbers
|
|
||||||
|
|
||||||
|
|
||||||
class BasicNumberClass:
|
|
||||||
def __init__(self, int_num=0, float_num=1, unit1=None, unit2=None):
|
|
||||||
self.int = int_num
|
|
||||||
self.float = decimal.Decimal(str(float_num))
|
|
||||||
if unit1:
|
|
||||||
self.units1 = unit1
|
|
||||||
else:
|
|
||||||
self.units1 = []
|
|
||||||
if unit2:
|
|
||||||
self.units2 = unit2
|
|
||||||
else:
|
|
||||||
self.units2 = []
|
|
||||||
|
|
||||||
def sort(self):
|
|
||||||
self.units1.sort()
|
|
||||||
self.units2.sort()
|
|
||||||
|
|
||||||
def float_int_check(self, int_=None, float_=None):
|
|
||||||
if not int_:
|
|
||||||
int_ = 1
|
|
||||||
if not float_:
|
|
||||||
float_ = decimal.Decimal(1.0)
|
|
||||||
while float_ > 10:
|
|
||||||
float_ / 10
|
|
||||||
int_ + 1
|
|
||||||
else:
|
|
||||||
while float_ < 0.1:
|
|
||||||
float_ * 10
|
|
||||||
int_ - 1
|
|
||||||
return [int_, float_]
|
|
||||||
|
|
||||||
def units(self) -> list or bool:
|
|
||||||
if (self.units1 == []) and (self.units2 == []):
|
|
||||||
return None
|
|
||||||
data = self.units1
|
|
||||||
data.append(self.units2)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return [self.float, self.int, self.units1, self.units2]
|
|
||||||
|
|
||||||
def __add__(self, other):
|
|
||||||
o_type = type(other)
|
|
||||||
if o_type == type(self):
|
|
||||||
self.sort()
|
|
||||||
other.sort()
|
|
||||||
if self.units() == other.units():
|
|
||||||
self_num = self.float * (10 ** self.int)
|
|
||||||
other_num = other.float * (10 ** other.float)
|
|
||||||
r_float = self_num + other_num
|
|
||||||
check = self.float_int_check(1, r_float)
|
|
||||||
self.float = check[0]
|
|
||||||
self.int = check[1]
|
|
||||||
elif o_type == type(decimal.Decimal('1.0')) and not self.units():
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __radd__(self, other):
|
|
||||||
self.__add__(self)
|
|
||||||
|
|
||||||
def __mul__(self, other):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __rmul__(self, other):
|
|
||||||
self.__mul__(self)
|
|
||||||
|
|
||||||
def __truediv__(self, other):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def basic_poi(poi_type=None) -> list:
|
|
||||||
if poi_type is None:
|
|
||||||
return BasicNumber(unit1='m', num=2)
|
|
||||||
if poi_type == 'chunk':
|
|
||||||
return [BasicNumber(unit1='chunk', num=2), BasicNumber(unit1='m', num=2)]
|
|
||||||
|
|
||||||
|
|
||||||
def basic_force() -> list:
|
|
||||||
return BasicNumber(unit1='N', num=2)
|
|
||||||
|
|
||||||
|
|
||||||
class ScientificNumber:
|
|
||||||
"""
|
|
||||||
A class of Scientific notation
|
|
||||||
give float and integer and unit
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self,
|
|
||||||
小数: Union[float, Decimal] = 1.0,
|
|
||||||
指数: int = 0,
|
|
||||||
乘单位: list = list,
|
|
||||||
除单位: list = list):
|
|
||||||
if not isinstance(小数, Decimal):
|
|
||||||
self.小数 = Decimal(小数)
|
|
||||||
else:
|
|
||||||
self.小数 = 小数
|
|
||||||
self.指数 = 指数
|
|
||||||
self.乘单位 = 乘单位
|
|
||||||
self.除单位 = 除单位
|
|
||||||
self.check()
|
|
||||||
|
|
||||||
def check(self):
|
|
||||||
while self.小数 > 10:
|
|
||||||
self.小数 /= 10
|
|
||||||
self.指数 += 1
|
|
||||||
while self.小数 < 1:
|
|
||||||
self.小数 *= 10
|
|
||||||
self.指数 -= 1
|
|
||||||
self.除单位.sort()
|
|
||||||
self.乘单位.sort()
|
|
@ -4,25 +4,17 @@
|
|||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
import atexit
|
import atexit
|
||||||
import inspect
|
import inspect
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
# from inspect import F
|
|
||||||
from os import PathLike
|
|
||||||
from time import strftime
|
from time import strftime
|
||||||
from logging import NOTSET, DEBUG, INFO, WARNING, ERROR, FATAL
|
from logging import NOTSET, DEBUG, INFO, WARNING, ERROR, FATAL
|
||||||
from types import FrameType
|
from types import FrameType
|
||||||
from typing import Optional, Union, Dict, Iterable, Tuple, Any, List, Callable
|
from typing import Optional, Union, Dict, Iterable, Tuple, Any
|
||||||
|
|
||||||
print(os.path.abspath(os.curdir))
|
# print(os.path.abspath(os.curdir))
|
||||||
os.chdir('../../')
|
|
||||||
sys.path.append('D:/githubs/DR')
|
|
||||||
sys.path.append(os.path.abspath('./Difficult_Rocket'))
|
|
||||||
|
|
||||||
from Difficult_Rocket.utils.thread import ThreadLock
|
|
||||||
|
|
||||||
# 如果想要直接使用 logger 来 logging
|
# 如果想要直接使用 logger 来 logging
|
||||||
# 直接调用 logger.debug() 即可
|
# 直接调用 logger.debug() 即可
|
||||||
@ -101,9 +93,24 @@ logger_configs = {
|
|||||||
},
|
},
|
||||||
'Color': {
|
'Color': {
|
||||||
'main_color': {
|
'main_color': {
|
||||||
'date': '\033[38;2;201;222;56m',
|
'file_time': '\033[38;2;201;222;56m',
|
||||||
'file': '\033[38;2;0;255;180m',
|
'main_time': '\033[38;2;201;222;56m',
|
||||||
'line': '\033[38;2;0;255;180m',
|
'file_name': '\033[38;2;0;255;180m',
|
||||||
|
'code_line': '\033[38;2;0;255;180m',
|
||||||
|
'logger': '\033[0m',
|
||||||
|
TRACE: {'info': '\033[38;2;138;173;244m', 'message': '\033[38;2;40;40;70m'},
|
||||||
|
FINE: {'info': '\033[35;48;2;44;44;54m', 'message': '\033[35m'},
|
||||||
|
DEBUG: {'info': '\033[38;2;133;138;149m', 'message': '\033[38;2;133;138;149m'},
|
||||||
|
INFO: {'info': '\033[0m', 'message': '\033[0m'},
|
||||||
|
WARNING: {'info': '\033[33m', 'message': '\033[33m'},
|
||||||
|
ERROR: {'info': '\033[31m', 'message': '\033[31m'},
|
||||||
|
FATAL: {'info': '\033[38;2;255;255;0;48;2;120;10;10m', 'message': '\033[38;2;255;255;0;48;2;120;10;10m'}
|
||||||
|
},
|
||||||
|
'DiGua_color': {
|
||||||
|
'file_time': '\033[38;2;201;222;56m',
|
||||||
|
'main_time': '\033[38;2;201;222;56m',
|
||||||
|
'file_name': '\033[38;2;0;255;180m',
|
||||||
|
'code_line': '\033[38;2;0;255;180m',
|
||||||
'logger': '\033[0m',
|
'logger': '\033[0m',
|
||||||
TRACE: {'info': '\033[34;48;2;44;44;54m', 'message': '\033[34;48;2;40;40;70m'},
|
TRACE: {'info': '\033[34;48;2;44;44;54m', 'message': '\033[34;48;2;40;40;70m'},
|
||||||
FINE: {'info': '\033[35;48;2;44;44;54m', 'message': '\033[35m'},
|
FINE: {'info': '\033[35;48;2;44;44;54m', 'message': '\033[35m'},
|
||||||
@ -119,13 +126,17 @@ logger_configs = {
|
|||||||
'mode': 'a',
|
'mode': 'a',
|
||||||
'encoding': 'utf-8',
|
'encoding': 'utf-8',
|
||||||
'level': TRACE,
|
'level': TRACE,
|
||||||
'file_name': './logs/{file_time}_logs.md'
|
'file_name': './logs/{file_time}_logs.md',
|
||||||
|
'cache_len': 10,
|
||||||
|
'cache_time': 1
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'Formatter': {
|
'Formatter': {
|
||||||
'MESSAGE': {
|
'MESSAGE': {
|
||||||
'format': '[{main_time}] [{logger_name}] {level} | {file_name}:{code_line} | {message}'
|
'format': '[{main_time}] [{logger_name}] {level} | {file_name}:{code_line} | {message}'
|
||||||
},
|
},
|
||||||
|
'file_name': 'no frame',
|
||||||
|
'code_line': 'no frame',
|
||||||
'file_time': {'strftime': '%Y-%m-%d %H-%M'},
|
'file_time': {'strftime': '%Y-%m-%d %H-%M'},
|
||||||
'main_time': {'strftime': '%Y-%m-%d %H-%M-%S:%%S'}, # %%S 三位毫秒
|
'main_time': {'strftime': '%Y-%m-%d %H-%M-%S:%%S'}, # %%S 三位毫秒
|
||||||
...: ...
|
...: ...
|
||||||
@ -133,6 +144,23 @@ logger_configs = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ThreadLock:
|
||||||
|
|
||||||
|
def __init__(self, the_lock: threading.Lock, time_out: Union[float, int] = 1 / 60) -> None:
|
||||||
|
self.lock = the_lock
|
||||||
|
self.time_out = time_out
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.lock.acquire(timeout=self.time_out)
|
||||||
|
if not self.lock.locked():
|
||||||
|
raise RuntimeError(f'Lock time Out with {self.time_out}')
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
if self.lock.locked():
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
|
|
||||||
class ListCache:
|
class ListCache:
|
||||||
"""一个线程安全的列表缓存"""
|
"""一个线程安全的列表缓存"""
|
||||||
|
|
||||||
@ -189,24 +217,23 @@ class ListCache:
|
|||||||
class LogFileCache:
|
class LogFileCache:
|
||||||
"""日志文件缓存"""
|
"""日志文件缓存"""
|
||||||
|
|
||||||
def __init__(self, file_conf: Dict, flush_time: Optional[Union[int, float]] = 1, log_cache_lens_max: int = 10):
|
def __init__(self, file_conf: dict, ):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@param file_conf: 日志文件配置
|
@param file_conf: 日志文件配置
|
||||||
@param flush_time: 刷新日志缓存,写入文件的时长间隔
|
|
||||||
@param log_cache_lens_max: 日志缓存在自动写入前的最大缓存长度
|
|
||||||
"""
|
"""
|
||||||
# 配置相关
|
# 配置相关
|
||||||
self._logfile_name = os.path.abspath(format_str(file_conf['file_name'])) # log 文件名称
|
self._logfile_name = os.path.abspath(format_str(file_conf['file_name'])) # log 文件名称
|
||||||
self.level = get_key_from_dict(file_conf, 'level', DEBUG)
|
self.level = get_key_from_dict(file_conf, 'level', DEBUG)
|
||||||
self.file_conf = file_conf
|
self.file_conf = file_conf
|
||||||
self.flush_time = flush_time # 缓存刷新时长
|
self.flush_time = file_conf['cache_time'] # 缓存刷新时长
|
||||||
self.cache_entries_num = log_cache_lens_max
|
self.cache_entries_num = file_conf['cache_len']
|
||||||
self.started = False
|
self.started = True
|
||||||
|
self.running = False
|
||||||
# 同步锁
|
# 同步锁
|
||||||
self.cache_lock = threading.Lock() # 主锁
|
self.cache_lock = threading.Lock() # 主锁
|
||||||
self.time_limit_lock = ThreadLock(self.cache_lock, time_out=1 / 60) # 直接用于 with 的主锁
|
self.time_limit_lock = ThreadLock(self.cache_lock, time_out=1 / 60) # 直接用于 with 的主锁
|
||||||
self.threaded_write = threading.Timer(1, self._log_file_time_write) # 基于 timer 的多线程
|
self.threaded_write = threading.Timer(1, self._log_file_time_write, kwargs={'thread': True}) # 基于 timer 的多线程
|
||||||
# 日志缓存表
|
# 日志缓存表
|
||||||
self.log_cache = ListCache(self.time_limit_lock)
|
self.log_cache = ListCache(self.time_limit_lock)
|
||||||
self.file_setup()
|
self.file_setup()
|
||||||
@ -222,7 +249,9 @@ class LogFileCache:
|
|||||||
def end_thread(self) -> None:
|
def end_thread(self) -> None:
|
||||||
"""结束日志写入进程,顺手把目前的缓存写入"""
|
"""结束日志写入进程,顺手把目前的缓存写入"""
|
||||||
self.cache_lock.acquire(blocking=True)
|
self.cache_lock.acquire(blocking=True)
|
||||||
self.threaded_write.cancel()
|
if self.running:
|
||||||
|
self.threaded_write.cancel()
|
||||||
|
self.running = False
|
||||||
self.started = False
|
self.started = False
|
||||||
self._log_file_time_write()
|
self._log_file_time_write()
|
||||||
atexit.unregister(self.end_thread)
|
atexit.unregister(self.end_thread)
|
||||||
@ -230,20 +259,22 @@ class LogFileCache:
|
|||||||
def start_thread(self) -> None:
|
def start_thread(self) -> None:
|
||||||
self.threaded_write.start()
|
self.threaded_write.start()
|
||||||
self.started = True
|
self.started = True
|
||||||
|
self.running = True
|
||||||
atexit.register(self.end_thread)
|
atexit.register(self.end_thread)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def logfile_name(self) -> PathLike:
|
def logfile_name(self) -> str:
|
||||||
self._logfile_name: PathLike
|
self._logfile_name: str
|
||||||
return self._logfile_name
|
return self._logfile_name
|
||||||
|
|
||||||
@logfile_name.setter
|
@logfile_name.setter
|
||||||
def logfile_name(self, value: PathLike) -> None:
|
def logfile_name(self, value: str) -> None:
|
||||||
with self.time_limit_lock:
|
with self.time_limit_lock:
|
||||||
self._logfile_name = value
|
self._logfile_name = value
|
||||||
|
|
||||||
def _log_file_time_write(self) -> None:
|
def _log_file_time_write(self, thread: bool = False) -> None:
|
||||||
"""使用 threading.Timer 调用的定时写入日志文件的函数"""
|
"""使用 threading.Timer 调用的定时写入日志文件的函数"""
|
||||||
|
print(f'write! {thread}{self.log_cache.cache}')
|
||||||
if self.log_cache:
|
if self.log_cache:
|
||||||
with self.time_limit_lock:
|
with self.time_limit_lock:
|
||||||
if self.log_cache:
|
if self.log_cache:
|
||||||
@ -252,6 +283,8 @@ class LogFileCache:
|
|||||||
mode=get_key_from_dict(self.file_conf, 'mode', 'a')) as log_file:
|
mode=get_key_from_dict(self.file_conf, 'mode', 'a')) as log_file:
|
||||||
log_file.writelines(self.log_cache.cache.copy())
|
log_file.writelines(self.log_cache.cache.copy())
|
||||||
self.log_cache.clear()
|
self.log_cache.clear()
|
||||||
|
if thread:
|
||||||
|
self.running = False
|
||||||
|
|
||||||
def write_logs(self, string: str, flush: bool = False) -> None:
|
def write_logs(self, string: str, flush: bool = False) -> None:
|
||||||
self.log_cache.append(string)
|
self.log_cache.append(string)
|
||||||
@ -260,25 +293,36 @@ class LogFileCache:
|
|||||||
return None
|
return None
|
||||||
if flush:
|
if flush:
|
||||||
self._log_file_time_write()
|
self._log_file_time_write()
|
||||||
|
if self.started and not self.running:
|
||||||
|
self.threaded_write = threading.Timer(1, self._log_file_time_write, kwargs={'thread': True}) # 基于 timer 的多线程
|
||||||
|
self.threaded_write.start()
|
||||||
|
self.running = True
|
||||||
|
|
||||||
|
|
||||||
class Logger:
|
class Logger:
|
||||||
"""shenjack logger"""
|
"""shenjack logger"""
|
||||||
|
|
||||||
def __init__(self, name: str = None, level: int = None, file_conf: Dict = None, colors: Dict[Union[int, str], Dict[str, str]] = None, formats=None, **kwargs) -> None:
|
def __init__(self,
|
||||||
|
name: str = None,
|
||||||
|
level: int = None,
|
||||||
|
file_conf: Dict = None,
|
||||||
|
colors: Dict[Union[int, str], Dict[str, str]] = None,
|
||||||
|
formats=None) -> None:
|
||||||
"""
|
"""
|
||||||
配置模式: 使用 kwargs 配置
|
配置模式: 使用 kwargs 配置
|
||||||
@param name: logger 名称 默认为 root
|
@param name: logger 名称 默认为 root
|
||||||
@param level: logging 输出等级 默认为 DEBUG(10)
|
@param level: logging 输出等级 默认为 DEBUG(10)
|
||||||
@param file_name: logging 写入文件名称 默认为 None(不写入)
|
@param file_conf: logger 的文件处理配置
|
||||||
|
@param colors: dict 颜色配置
|
||||||
|
@param formats: 格式化配置
|
||||||
"""
|
"""
|
||||||
self.name = name or 'root'
|
self.name = name or 'root'
|
||||||
self.level = level if level is not None else DEBUG
|
self.level = level if level is not None else DEBUG
|
||||||
self.colors = colors or logger_configs['Color']['main_color']
|
self.colors = colors or logger_configs['Color']['main_color']
|
||||||
self.formats = formats or logger_configs['Formatter']
|
self.formats = formats or logger_configs['Formatter'].copy()
|
||||||
|
self.formats['logger_name'] = f'{self.colors["logger"]}{self.name}{color_reset_suffix}'
|
||||||
if file_conf:
|
if file_conf:
|
||||||
self.file_cache = LogFileCache(file_conf=file_conf)
|
self.file_cache = LogFileCache(file_conf=file_conf)
|
||||||
self.file_cache.start_thread()
|
|
||||||
else:
|
else:
|
||||||
self.file_cache = False
|
self.file_cache = False
|
||||||
self.warn = self.warning
|
self.warn = self.warning
|
||||||
@ -293,6 +337,7 @@ class Logger:
|
|||||||
# self.file_cache.level if self.file_cache else False,
|
# self.file_cache.level if self.file_cache else False,
|
||||||
# level >= self.level,
|
# level >= self.level,
|
||||||
# self.file_cache and (level >= self.file_cache.level))
|
# self.file_cache and (level >= self.file_cache.level))
|
||||||
|
self.file_cache: Union[bool, LogFileCache]
|
||||||
if level < self.level and self.file_cache and (level < self.file_cache.level):
|
if level < self.level and self.file_cache and (level < self.file_cache.level):
|
||||||
return None
|
return None
|
||||||
if not frame:
|
if not frame:
|
||||||
@ -311,26 +356,20 @@ class Logger:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def format_text(self, level: int, text: str, frame: Optional[FrameType]) -> str:
|
def format_text(self, level: int, text: str, frame: Optional[FrameType]) -> str:
|
||||||
from Difficult_Rocket import DR_option, DR_runtime
|
|
||||||
level_with_color = f"[{self.colors[level]['info']}{level_name_map[level]}{color_reset_suffix}]"
|
level_with_color = f"[{self.colors[level]['info']}{level_name_map[level]}{color_reset_suffix}]"
|
||||||
level_with_color = f"{level_with_color}{' ' * (9 - len_without_color_maker(level_with_color))}"
|
level_with_color = f"{level_with_color}{' ' * (9 - len_without_color_maker(level_with_color))}"
|
||||||
formats = self.formats.copy()
|
formats = self.formats.copy()
|
||||||
formats.pop('MESSAGE')
|
if frame is not None:
|
||||||
if frame is None:
|
formats['file_name'] = f"{self.colors['file_name']}{os.path.split(frame.f_code.co_filename)[-1]}{color_reset_suffix}"
|
||||||
formats['file_name'] = 'no frame'
|
formats['code_line'] = f"{self.colors['code_line']}{frame.f_lineno}{color_reset_suffix}"
|
||||||
formats['code_line'] = 'no frame'
|
|
||||||
else:
|
|
||||||
formats['file_name'] = f"{self.colors['file']}{os.path.split(frame.f_code.co_filename)[-1]}{color_reset_suffix}"
|
|
||||||
formats['code_line'] = f"{self.colors['line']}{frame.f_lineno}{color_reset_suffix}"
|
|
||||||
now_time = str(time.time())
|
now_time = str(time.time())
|
||||||
for key, value in formats.items():
|
for key, value in formats.items():
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
if 'strftime' in value:
|
if 'strftime' in value:
|
||||||
value['strftime']: str
|
value['strftime']: str
|
||||||
formats[key] = f"{self.colors['date']}{strftime(value['strftime'].replace('%%S', now_time[now_time.find('.') + 1:now_time.find('.') + 4]))}{color_reset_suffix}"
|
formats[key] = f"{self.colors[key]}{strftime(value['strftime'].replace('%%S', now_time[now_time.find('.') + 1:now_time.find('.') + 4]))}{color_reset_suffix}"
|
||||||
print_text = self.formats['MESSAGE']['format'].format(level_with_color=level_with_color,
|
print_text = self.formats['MESSAGE']['format'].format(level_with_color=level_with_color,
|
||||||
level=level_with_color, message=text,
|
level=level_with_color, message=text,
|
||||||
logger_name=self.name,
|
|
||||||
**formats)
|
**formats)
|
||||||
return print_text
|
return print_text
|
||||||
|
|
||||||
@ -420,8 +459,36 @@ def logging_color() -> Dict:
|
|||||||
return {'info': ..., 'message': ...}
|
return {'info': ..., 'message': ...}
|
||||||
|
|
||||||
|
|
||||||
def setup_logger() -> None:
|
def gen_file_conf(file_name: str,
|
||||||
...
|
file_level: int = DEBUG,
|
||||||
|
file_mode: str = 'a',
|
||||||
|
file_encoding: str = 'utf-8',
|
||||||
|
file_cache_len: int = 10,
|
||||||
|
file_cache_time: Union[int, float] = 1) -> dict:
|
||||||
|
return {'file_name': file_name,
|
||||||
|
'level': file_level,
|
||||||
|
'mode': file_mode,
|
||||||
|
'encoding': file_encoding,
|
||||||
|
'cache_len': file_cache_len,
|
||||||
|
'cache_time': file_cache_time}
|
||||||
|
|
||||||
|
|
||||||
|
def gen_color_conf(**colors) -> dict:
|
||||||
|
default_color = logger_configs['Color']['main_color'].copy()
|
||||||
|
default_color.update(colors)
|
||||||
|
return default_color
|
||||||
|
|
||||||
|
|
||||||
|
def logger_with_default_settings(name: str,
|
||||||
|
level: int = DEBUG,
|
||||||
|
file_conf: dict = None,
|
||||||
|
colors: dict = None,
|
||||||
|
formats: dict = None) -> Logger:
|
||||||
|
return Logger(name=name,
|
||||||
|
level=level,
|
||||||
|
file_conf=gen_file_conf(**file_conf),
|
||||||
|
colors=gen_color_conf(**colors),
|
||||||
|
formats=logger_configs['Formatter'].copy().update(formats))
|
||||||
|
|
||||||
|
|
||||||
def add_dict_config_to_global(some_dict: Union[dict, list, str], name: str) -> dict:
|
def add_dict_config_to_global(some_dict: Union[dict, list, str], name: str) -> dict:
|
||||||
@ -437,15 +504,6 @@ def add_dict_config_to_global(some_dict: Union[dict, list, str], name: str) -> d
|
|||||||
return logger_configs # 修改过的 logger 配置
|
return logger_configs # 修改过的 logger 配置
|
||||||
|
|
||||||
|
|
||||||
def add_kwargs_to_global(**kwargs) -> dict:
|
|
||||||
"""
|
|
||||||
|
|
||||||
@param kwargs: 你要改的 logger配置
|
|
||||||
@return: 修改过的 logger 配置
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
def get_logger(name: str = 'root') -> Logger:
|
def get_logger(name: str = 'root') -> Logger:
|
||||||
"""
|
"""
|
||||||
此函数用于从 global_config 中取出对应的配置建立一个相应的 logger
|
此函数用于从 global_config 中取出对应的配置建立一个相应的 logger
|
||||||
@ -456,41 +514,38 @@ def get_logger(name: str = 'root') -> Logger:
|
|||||||
the_config = logger_configs['Logger'][name]
|
the_config = logger_configs['Logger'][name]
|
||||||
else:
|
else:
|
||||||
the_config = logger_configs['Logger']['root']
|
the_config = logger_configs['Logger']['root']
|
||||||
a_logger = Logger(name=name,
|
return Logger(name=name,
|
||||||
level=the_config['level'],
|
level=the_config['level'],
|
||||||
file_conf=logger_configs['File'][the_config['file']] if 'file' in the_config else None,
|
file_conf=logger_configs['File'][the_config['file']] if 'file' in the_config else None,
|
||||||
colors=logger_configs['Color'][get_key_from_dict(the_config, 'color', 'main_color')],
|
colors=logger_configs['Color'][get_key_from_dict(the_config, 'color', 'main_color')],
|
||||||
formats=logger_configs['Formatter'])
|
formats=logger_configs['Formatter'])
|
||||||
return a_logger
|
|
||||||
|
|
||||||
|
def test_logger(the_logger: Logger):
|
||||||
|
the_logger.trace('tracing')
|
||||||
|
the_logger.fine('some fine!')
|
||||||
|
the_logger.debug('debugging')
|
||||||
|
the_logger.info("Hello World!!")
|
||||||
|
the_logger.warn('warning')
|
||||||
|
the_logger.error('error haaaa')
|
||||||
|
the_logger.fatal('oh no')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
os.chdir('githubs/DR')
|
os.chdir('D:/githubs/DR')
|
||||||
# 在这里可以使用 add_kwargs_to_global
|
|
||||||
logger = Logger(name="Main", level=NOTSET)
|
logger = Logger(name="Main", level=NOTSET)
|
||||||
for x in range(5):
|
logger.info('my name is:', logger.name)
|
||||||
logger.trace('tracing')
|
|
||||||
logger.fine('some fine!')
|
|
||||||
logger.debug('debugging')
|
|
||||||
logger.info("Hello World!!")
|
|
||||||
logger.warn('warning')
|
|
||||||
logger.error('error haaaa')
|
|
||||||
logger.fatal('oh no')
|
|
||||||
a_logger = get_logger('client')
|
a_logger = get_logger('client')
|
||||||
a_logger.trace('tracing')
|
a_logger.trace('tracing')
|
||||||
# time.sleep(5)
|
time.sleep(1.1)
|
||||||
a_logger.fine('some fine!')
|
a_logger.fine('some fine!')
|
||||||
a_logger.debug('debugging')
|
a_logger.debug('debugging')
|
||||||
# time.sleep(5)
|
time.sleep(1.1)
|
||||||
a_logger.info("Hello World!!")
|
a_logger.info("Hello World!!")
|
||||||
a_logger.warn('warning')
|
a_logger.warn('warning')
|
||||||
a_logger.error('error haaaa')
|
a_logger.error('error haaaa')
|
||||||
a_logger.fatal('oh no')
|
a_logger.fatal('oh no')
|
||||||
|
logger.info('my name is:', logger.name)
|
||||||
for x in range(5):
|
for x in range(5):
|
||||||
a_logger.trace('tracing')
|
test_logger(logger)
|
||||||
a_logger.fine('some fine!')
|
test_logger(a_logger)
|
||||||
a_logger.debug('debugging')
|
|
||||||
a_logger.info("Hello World!!")
|
|
||||||
a_logger.warn('warning')
|
|
||||||
a_logger.error('error haaaa')
|
|
||||||
a_logger.fatal('oh no')
|
|
||||||
|
@ -16,13 +16,13 @@ import threading
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
from Difficult_Rocket import crash
|
from Difficult_Rocket import DR_option, crash
|
||||||
from Difficult_Rocket.exception.threading import LockTimeOutError
|
from Difficult_Rocket.exception.threading import LockTimeOutError
|
||||||
|
|
||||||
|
|
||||||
class Threads(threading.Thread):
|
class Threads(threading.Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
if crash.record_thread:
|
if DR_option.record_thread:
|
||||||
crash.all_thread.append(self)
|
crash.all_thread.append(self)
|
||||||
super().run()
|
super().run()
|
||||||
|
|
||||||
@ -34,27 +34,14 @@ class ThreadLock:
|
|||||||
self.time_out = time_out
|
self.time_out = time_out
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
# print('enter!')
|
|
||||||
self.lock.acquire(timeout=self.time_out)
|
self.lock.acquire(timeout=self.time_out)
|
||||||
if not self.lock.locked():
|
if not self.lock.locked():
|
||||||
raise LockTimeOutError('')
|
raise LockTimeOutError(f'Lock time Out with {self.time_out}')
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
if self.lock.locked():
|
if self.lock.locked():
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
if (exc_type is None) and (exc_val is None) and (exc_tb is None):
|
|
||||||
# 没有出 bug
|
|
||||||
# print('exit with no error')
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
# 出 bug 了
|
|
||||||
# print(f'exit with error {exc_type} {exc_val}')
|
|
||||||
return None
|
|
||||||
|
|
||||||
# def __del__(self):
|
|
||||||
# print('del me!')
|
|
||||||
# self.__del__()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
Loading…
Reference in New Issue
Block a user