Hi Peter and Jean-Michel,
thanks for all your hints and pieces of code.
It took me a while to play around with what I got from you (and some
study of Vinay's module documentation.
Now I have come up with a more complete solution I'm quite satisfied
with. And I would be very glad to receive your comments on my code
indicating what I could do better, given that I'm still at the very
beginning with python.
Cheers + TIA
Hellmut
Here is my module and a corresponding test program:
l...@sylvester hw_logg $ cat loc_logg.py
#!/bin/env python
# -*- coding: utf-8 -*-
"""Hw's local logging module
To be done:
Factorize 'trace' decorator to own module
(to permit dependency on debug level) ???
"""
import sys # Basic system functions
import logging # Logging base
import logging.handlers
import inspect # monkey patch caller filename
# --- color change strings for terminal output ---
#
pc_yell = '\033[01;93m'
pc_purp = '\033[01;33m'
pc_gren = '\033[01;92m'
pc_blue = '\033[01;94m'
#
pc_bold = '\033[01;1m'
pc_norm = '\033[0m'
#
pc_reed = '\033[01;91m'
pc_cyan = '\033[01;96m'
level_color = {
'fatal': pc_yell,
'error': pc_yell,
'warning': pc_purp,
'info': pc_gren,
'debug': pc_blue,
'bold': pc_bold,
'normal': pc_norm
}
# --- define string building help function ---
#
def argskw_2_string(*args, **kwargs):
"""Generate String from *args and **kwargs
Return string with
*args list (comma separated) in first line
**kwargs key=val list (comma separated) in second line
"""
_str_lines = []
if args:
_args_strings = ''
for a in args:
_args_strings += str(a) + ', '
_str_lines.append(_args_strings)
if kwargs:
_kwargs_strings = ''
for k in kwargs:
_kwargs_strings += str(k)+' = '+str(kwargs[k]) + ', '
_str_lines.append(_kwargs_strings)
return ''.join(_str_lines)
# --- Class for all logging functionality ---
#
class locLogg():
_logger = None
def __init__(self, newlogg=None):
if not locLogg._logger:
locLogg._logger = newlogg
def init_logging(self,
loclogg_output='line', # stream or/and file
loclogg_fname='loggfile.txt',
loclogg_dblevel='DEBUG'
):
"""Initiate logging with locLogg._logger
Defines the logging handler to be used
and initiates it.
Possible values for loclogg_output:
line ==> output to console
file ==> log_file must be given
both ==> log_file must be given
null ==> no logging (NullHandler)
"""
locLogg._logger.handlers=[]
if loclogg_output in ('null'):
class NullHandler(logging.Handler):
def emit(self, record):
pass
locLogg._logger.addHandler(NullHandler())
if loclogg_output in ('line', 'both'):
locLogg._logger.addHandler(logging.StreamHandler())
if loclogg_output in ('file', 'both'):
locLogg._logger.addHandler(
logging.handlers.RotatingFileHandler(loclogg_fname,
maxBytes=200000, backupCount=5)
)
for _loc_logger in locLogg._logger.handlers:
_loc_logger.setFormatter(logging.Formatter(
'%(asctime)s ' + \
'%(custom_filename)s <%(custom_lineno)d>:' + \
'%(levelname)s %(message)s'))
# Can this be done better ?
_loc_levels = {'NOTSET': 0, 'DEBUG': 10,
'INFO': 20, 'WARNING': 30, 'ERROR': 40, 'CRITICAL': 50}
locLogg._logger.setLevel(_loc_levels[loclogg_dblevel])
def info_log(self, msg, *args, **kwargs):
previousFrame = inspect.currentframe().f_back
locLogg._logger.info(str(level_color['info'])+msg+pc_norm + \
' ' + argskw_2_string(*args, **kwargs),
extra={'custom_lineno': previousFrame.f_lineno,
'custom_filename': previousFrame.f_code.co_filename })
def debug_log(self, msg, *args, **kwargs):
previousFrame = inspect.currentframe().f_back
locLogg._logger.debug(str(level_color['debug'])+msg+pc_norm + \
' ' + argskw_2_string(*args, **kwargs),
extra={'custom_lineno':previousFrame.f_lineno,
'custom_filename': previousFrame.f_code.co_filename })
def warn_log(self, msg, *args, **kwargs):
previousFrame = inspect.currentframe().f_back
locLogg._logger.debug(str(level_color['warning'])+msg+pc_norm + \
' ' + argskw_2_string(*args, **kwargs),
extra={'custom_lineno':previousFrame.f_lineno,
'custom_filename': previousFrame.f_code.co_filename })
def error_log(self, msg, *args, **kwargs):
previousFrame = inspect.currentframe().f_back
locLogg._logger.error(str(level_color['error'])+msg+pc_norm + \
' ' + argskw_2_string(*args, **kwargs),
extra={'custom_lineno':previousFrame.f_lineno,
'custom_filename': previousFrame.f_code.co_filename })
def fatal_log(self, msg, *args, **kwargs):
previousFrame = inspect.currentframe().f_back
locLogg._logger.fatal(str(level_color['fatal'])+msg+pc_norm + \
' ' + argskw_2_string(*args, **kwargs),
extra={'custom_lineno':previousFrame.f_lineno,
'custom_filename': previousFrame.f_code.co_filename })
# --- Permit definition of a tracing decorator ---
from decorator import decorator
@decorator
def trace(f, *args, **kw):
print "@trace: calling %s with args %s, %s" % (f.func_name, args, kw)
return f(*args, **kw)
# cf. doc of Michele Simoniato's decorator module
if __name__ == '__main__':
_logger = logging.getLogger('jmp_logg__main__')
foo = locLogg(_logger)
foo.init_logging()
foo.info_log('a foo info')
foo.info_log('another bar info', 1,2,3, a=11, b=22, c=44)
foo.debug_log('a debug bar info', 'a', '1aA', qwe=2, asd=99)
foo.warn_log('a test info', 'ggg', '2U2', yxcv=2, asdf=99)
try:
b = 123
c = 0
a = b / c
except:
foo.fatal_log('Division by zero', b=123, c=0)
l...@sylvester hw_logg $ cat test_loclogg.py
#!/bin/env python
# -*- coding: utf-8 -*-
import logging
_logger = logging.getLogger()
import sys
pyDevelDir = '/home/leo/leo/brbeit/py-devel/Modules'
sys.path.append(pyDevelDir)
from hw_logg.loc_logg import locLogg
foo = locLogg(_logger)
foo.init_logging(
loclogg_output='both',
loclogg_dblevel='DEBUG')
import loc_module as jm
foo.info_log('First info with args in string: %d %d %d' % (1,2,3))
foo.warn_log('First warning')
foo.debug_log('First debug message TestTestTest', '----------', 4,5,6,
12*25, d=34, e='qwe')
foo.debug_log('Before calling jm.doIt()')
jm.doIt(True)
foo.info_log('Second info with kwargs separate:', a=11,b=22,c=33)
x = jm.MyClass(1, 2, 'abc')
x.mymethod()
x.mymethod(123, 234, a=1, b=2, c=3)
try:
jm.doIt(0)
except Exception, e:
foo.error_log(str(e), 1,5,8)
foo.fatal_log('Fatal message')
l...@sylvester hw_logg $ cat loc_module.py
# -*- coding: utf-8 -*-
import logging
_logger = logging.getLogger('jmp_logger')
import sys
pyDevelDir = '/home/leo/leo/brbeit/py-devel/Modules'
sys.path.append(pyDevelDir)
from hw_logg.loc_logg import locLogg, trace
foo = locLogg(_logger)
foo.info_log("Start importing "+__name__)
def doIt(yn=None):
foo.debug_log("doin' stuff, yn =", str(yn)) # logLevel at calling
point !
print '=====> Output from doIt:', yn
#do stuff...but suppose an error occurs?
if yn:
foo.info_log('yn: good value')
else:
raise TypeError, "bogus type error for testing"
class MyClass(object):
@trace
def __init__(self, *args, **kwargs):
print 'MyClass.__init__'
@trace
def mymethod(self, *args, **kwargs):
print 'MyClass.mymethod'
foo.info_log("End importing "+__name__)
--
Dr. Hellmut Weber m...@hellmutweber.de
Degenfeldstraße 2 tel +49-89-3081172
D-80803 München-Schwabing mobil +49-172-8450321
please: No DOCs, no PPTs. why: tinyurl.com/cbgq
--
http://mail.python.org/mailman/listinfo/python-list