# -*- coding:utf-8 -*-
# -----------------------------------------------------------------------------------------------------------
# 调用系统库,三方库
# -----------------------------------------------------------------------------------------------------------
import os
import subprocess
import time
import traceback
import logging
import sys
# -----------------------------------------------------------------------------------------------------------
# 对外接口
# -----------------------------------------------------------------------------------------------------------
__all__ = ['print_log', 'decorator_start_to_end_info', 'interface_info_log',
'function_info_log', 'Py_Logger', 'log_path']
# -----------------------------------------------------------------------------------------------------------
# 本地参数
# -----------------------------------------------------------------------------------------------------------
cur_file = os.path.abspath(__file__)
cur_path = os.path.dirname(cur_file)
_parameter = '*' * 40
log_file = 'onekey_install.log'
error_log_file = 'error.log'
log_dir = os.path.realpath(os.path.join(cur_path, '../log'))
log_path = os.path.join(log_dir, log_file)
error_log_path = os.path.join(log_dir, error_log_file)
py_logger = None
# -----------------------------------------------------------------------------------------------------------
# 主体
# -----------------------------------------------------------------------------------------------------------
reload(sys)
sys.setdefaultencoding('utf-8')
def local_execute(cmd):
p = subprocess.Popen(cmd.encode('utf-8'), stdout=sys.stdout, stderr=sys.stderr, shell=True)
p.wait()
returncode = p.returncode
return returncode
# python logging
class Py_Logger(object):
log_level = logging.DEBUG
def __init__(self):
self.logger = logging.getLogger(__name__)
self.log_path = log_path
self.error_log_path = error_log_path
cmd = "mkdir -p %s" % log_dir
local_execute(cmd)
# if not os.path.exists(log_dir):
# # os.mkdir(log_dir)
# os.makedirs(log_dir)
# 清空当前文件的logging
# self.logger.handlers = []
# self.release()
if not self.logger.handlers:
# logger 配置等级
self.logger.setLevel(logging.DEBUG)
# file handler
self.fh = logging.FileHandler(log_path, mode='a', encoding='utf-8')
self.fh.setLevel(logging.DEBUG)
self.err_fh = logging.FileHandler(self.error_log_path, mode='a', encoding='utf-8', delay=True)
self.err_fh.setLevel(logging.ERROR)
# console handler
self.ch = logging.StreamHandler()
self.ch.setLevel(logging.INFO)
# set format for handlers
f_format = "%(asctime)s [%(levelname)s] - [processNum:%(process)d][%(processName)s] - " \
"[threadNum:%(thread)d][%(threadName)s] - %(message)s"
c_format = "%(asctime)s [%(levelname)s] - %(message)s"
formatter = logging.Formatter(f_format)
c_formatter = logging.Formatter(c_format)
self.fh.setFormatter(formatter)
self.ch.setFormatter(c_formatter)
self.err_fh.setFormatter(formatter)
# 添加handler
self.logger.addHandler(self.fh)
self.logger.addHandler(self.err_fh)
console_flag = self.get_console_flag()
if console_flag:
self.logger.addHandler(self.ch)
# 获取console_flag
def get_console_flag(self):
console_flag = True
console_flag_file = os.path.join(cur_path, 'console_flag.txt')
if os.path.isfile(console_flag_file):
with open(console_flag_file, 'r') as f:
console_flag = False if f.read().strip() == '0' else True
return console_flag
def info(self, message=None):
self.logger.info(message)
def debug(self, message=None):
self.logger.debug(message)
def warning(self, message=None):
self.logger.warning(message)
def error(self, message=None):
self.logger.error(message)
def exception(self, message=None):
self.logger.exception(message)
def critical(self, message=None):
self.logger.critical(message)
def release(self):
"""
释放句柄
:return:
"""
try:
self.fh.close()
self.err_fh.close()
self.ch.close()
except:
pass
finally:
try:
for _hd in self.logger.handlers:
self.logger.removeHandler(_hd)
except:
pass
def log(self, level, msg):
try:
if level == 'DEBUG':
self.debug(msg)
elif level == 'INFO':
self.info(msg)
elif level == 'WARNING' or level == 'WARN':
self.warning(msg)
elif level == 'ERROR':
self.error(msg)
elif level == 'EXCEPTION' or level == 'EXCEPT':
self.exception(msg)
elif level == 'CRITICAL':
self.critical(msg)
else:
print('level should be DEBUG, INFO, WARNING, ERROR, EXCEPT, CRITICAL.')
self.info(msg)
except KeyError as err:
print(err)
except Exception as err:
raise Exception(err)
finally:
pass
# self.release()
def print_log_by_py_logger(level, msg):
py_logger = Py_Logger()
py_logger.log(level, msg)
def print_log(level, msg, filename='<empty>', lineno=0):
"""
print msg to console and/or log file.
When run in robot, print msg to console or log file(log.html).
When not run in robot, print msg to console and log file:
log in Linux: $HOME/log/autotest.log
log in Windows: D:\\log\\autotest.log
Args:
| level | candidates are DEBUG, INFO, WARNING, ERROR |
| msg | log msg |
"""
# get the caller's filename, lineno, ...
# format: (filename, line number, function name, text)
# funcname = '<empty>'
stack = traceback.extract_stack()
if len(stack) >= 2:
if filename == '<empty>':
filename = os.path.basename(stack[-2][0])
lineno = stack[-2][1]
# funcname = stack[-2][2]
# msg = '%s(%d):%s - %s' % (filename, lineno, funcname, msg)
msg = '%s(%d) - %s' % (filename, lineno, msg)
print_log_by_py_logger(level, msg)
def interface_info_log(_key, _filename, _log_level='DEBUG', _info='START'):
"""
:param _key: 功能说明,一般使用函数名即可,
:param _filename: 文件名, '<empty>'时将自动获取
:param _log_level: 日志级别,一般在 INFO DEBUG ERROR 中选择
:param _info: 标志类型,一般在 START FAIL SUCCESS 中选择
:return:
"""
_parameter = '*' * 40
# 函数的提示
print_log(_log_level, _parameter, filename=_filename)
print_log(_log_level, '[~{0}~] [{1}]'.format(_info, _key), filename=_filename)
print_log(_log_level, _parameter, filename=_filename)
def function_info_log(_key, _filename, _log_level='DEBUG', _info='START'):
"""
:param _key: 功能说明,一般使用函数名即可,
:param _filename: 文件名, '<empty>'时将自动获取
:param _log_level: 日志级别,一般在 INFO DEBUG ERROR 中选择
:param _info: 标志类型,一般在 START FAIL SUCCESS 中选择
:return:
"""
_parameter = '*' * 6
# 函数的提示
print_log(_log_level, '{2} [~{0}~] [{1}] {2}'.format(_info, _key, _parameter), filename=_filename)
def info_log(_key, _filename='<empty>', _model='function', _log_level='DEBUG', _info='START', ):
"""
根据需要打印不同格式的日志
:param _key:功能说明,一般使用函数名即可,
:param _filename: 文件名, '<empty>'时将自动获取
:param _model: 一般在function interface中选择
:param _log_level:日志级别,一般在 INFO DEBUG ERROR 中选择
:param _info:标志类型,一般在 START FAIL SUCCESS 中选择
:return:
"""
_info_log_dict = {'function': function_info_log,
'interface': interface_info_log
}
return _info_log_dict[_model](_key, _filename, _log_level, _info)
def decorator_start_to_end_info(_model='function', _log_level='DEBUG'):
"""
有装饰器入参,有函数入参
:input: _model['function', 'interface'], _log_level['INFO', 'DEBUG']
:return: 新函数
"""
def decorator_function(func):
def decorator_function_add(*args, **kwargs):
# 获取真实的文件名
filename = '<empty>'
stack = traceback.extract_stack()
if len(stack) >= 2:
filename = os.path.basename(stack[-2][0])
# 获取真实的函数名
func_name = func.__name__
# 开始标志
info_log(func_name, _model=_model, _log_level=_log_level, _info='START', _filename=filename)
start_time = time.time()
# 获取全部的函数入参,并格式化
input_param = ''
if all([args, not kwargs]):
input_param = args
elif all([kwargs, not args]):
input_param = kwargs
elif all([not args, not kwargs]):
input_param = ''
else:
input_param = (args, kwargs)
print_log(_log_level, 'func_name:{0} , input parameter:{1}'.format(func_name, input_param),
filename=filename)
# 执行真实的函数
result = func(*args, **kwargs)
# 计算执行时间
end_time = time.time()
exe_time = end_time - start_time
print_log(_log_level, 'function {0} exe_time is {1}(s)'.format(func.__name__, exe_time),
filename=filename)
# 结束标志
info_log(func_name, _model=_model, _log_level=_log_level, _info='SUCCESS', _filename=filename)
return result
return decorator_function_add
return decorator_function
if __name__ == '__main__':
print_log("INFO", "INFO")
print_log("ERROR", "ERROR")
print_log("WARNING", "WARNING")
python日志模块logging使用
最新推荐文章于 2023-11-27 11:13:05 发布