我看到这个非常常用的代码我用来设置日志记录。
def has_host_running(self):
log = CustomLogger.action_logger(name=sys._getframe().f_code.co_name, **self.menvargs)
result = self.bash_query.check_is_server_available(log)
self.results[sys._getframe().f_code.co_name] = result
log.debug('result: {}'.format(result))
return result
寻找实现此行为的干燥方法。 关键是我需要能够从 函数和任何子函数调用中引用/调用日志语句。
********* EDIT2 **************** ***************
我可以开始工作的最优雅的草率解决方案。 松散地改编自:https://wiki.python.org/moin/PythonDecoratorLibrary#Controllable_DIY_debug
heavily based on https://wiki.python.org/moin/PythonDecoratorLibrary#Controllable_DIY_debug
class ActionLog:
def init(self):
pass
def __call__(self, f):
log = self.get_actionlogger(name=f.func_name)
def newf(log, *args, **kwds):
# pre-function call actions:
log.debug('Start.')
log.debug(' info: params= {args}, {kwds}'.format(args=args, kwds=kwds))
# function call
f_result = f(log, *args, **kwds)
# post-function call actions:
log.debug(' info: result= {result}'.format(result=f_result))
log.debug('Complete.')
return f_result
# changes to be made to returned function
newf.__doc__ = f.__doc__
return newf(log)
def get_actionlogger(self, name, **kwargs):
import logging
import ast
from Helper import ConfigManager
logname = 'action.{func_name}'.format(func_name=name)
logger = logging.getLogger(logname)
# value stored in ini file.
# either DEBUG or ERROR right now.
# todo: store actual logging_level
# todo: store an array/dict for log_name in .ini
# this will allow multiple parameters to be stored within the single entry.
# ex:
# action.check_stuff: logging_level=DEBUG,handler_stream=TRUE,handler_file=stuff.log,formatter='{name} - {message}
conf_logging_level = ConfigManager('config.ini').get_section_dict('CustomLogging_Level').get(logname, 'DEBUG')
logging_level = logging.DEBUG
if conf_logging_level == 'DEBUG':
logging_level = logging.DEBUG
if conf_logging_level == 'ERROR':
logging_level = logging.ERROR
logger.setLevel(logging_level)
# very hacky
# while logging.getLogger is a singleton, adding the handler is not.
# without this check, this code will result in duplicate handlers added.
# currently will not edit/replace the existing handler.
# currently will not allow another handler to be added after the first.
# main issue here is that I can't figure out how to determine labels/names within logger.handlers
# todo: properly label handler
# todo: check for existing labels & types (file, stream, etc)
if len(logger.handlers) == 0:
ch = logging.StreamHandler()
ch.setLevel(logging_level)
ch.set_name = logname
# create formatter
formatter = logging.Formatter(' %(name)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
return logger
def __call__(self, f):
log = self.get_actionlogger(name=f.func_name)
def newf(log, *args, **kwds):
# pre-function call actions:
log.debug('Start.')
log.debug(' info: params= {args}, {kwds}'.format(args=args, kwds=kwds))
# function call
f_result = f(log, *args, **kwds)
# post-function call actions:
log.debug(' info: result= {result}'.format(result=f_result))
log.debug('Complete.')
return f_result
# changes to be made to returned function
newf.__doc__ = f.__doc__
return newf(log)
def get_actionlogger(self, name, **kwargs):
import logging
import ast
from Helper import ConfigManager
logname = 'action.{func_name}'.format(func_name=name)
logger = logging.getLogger(logname)
# value stored in ini file.
# either DEBUG or ERROR right now.
# todo: store actual logging_level
# todo: store an array/dict for log_name in .ini
# this will allow multiple parameters to be stored within the single entry.
# ex:
# action.check_stuff: logging_level=DEBUG,handler_stream=TRUE,handler_file=stuff.log,formatter='{name} - {message}
conf_logging_level = ConfigManager('config.ini').get_section_dict('CustomLogging_Level').get(logname, 'DEBUG')
logging_level = logging.DEBUG
if conf_logging_level == 'DEBUG':
logging_level = logging.DEBUG
if conf_logging_level == 'ERROR':
logging_level = logging.ERROR
logger.setLevel(logging_level)
# very hacky
# while logging.getLogger is a singleton, adding the handler is not.
# without this check, this code will result in duplicate handlers added.
# currently will not edit/replace the existing handler.
# currently will not allow another handler to be added after the first.
# main issue here is that I can't figure out how to determine labels/names within logger.handlers
# todo: properly label handler
# todo: check for existing labels & types (file, stream, etc)
if len(logger.handlers) == 0:
ch = logging.StreamHandler()
ch.setLevel(logging_level)
ch.set_name = logname
# create formatter
formatter = logging.Formatter(' %(name)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
return logger
@ActionLog()
def check_stuff(log, *args, **kwds):
result = True
log.debug(' info: text call from within function.')
return result
所以它适用于一个参数" log"被传入课堂。如果类没有log参数,则不起作用。如果还有其他参数,我不确定如何处理...可能使用* args或** kwargs,但此解决方案无法处理。
关于代码格式化的道歉...我似乎无法将类装饰器与装饰的func和func调用放在同一个块中。
* v3.0 * v2有多个参数的问题。解决了这个并简化了v3。
if check_stuff:
print 'check_stuff is true.'
这样做效果更好,并且已经取代了我的大多数样板记录调用,以获取采用单个参数的操作。
仍然遇到名为args vs kwargs的问题。我想直接传递args并将我的自定义项添加到kwargs,但这有一些问题。