principlepythonMinor
How's my approach to logging?
Viewed 0 times
loggingapproachhow
Problem
I was surprised that I didn't find this approach to logging anywhere while reading up on the subject. So, naturally, I think I may be doing something wrong. I set up some simple tests, and this seems to work:
First, the source:
``
detail should be printed to the terminal
"""
log.level = log.level.upper()
logger = logging.getLogger(log.name)
logger.setLevel(log.level)
formatter = logging.Formatter(log.format)
formatter.datefmt = log.datefmt
pretty_date = datetime.date.strftime(datetime.datetime.now(), log.datefmt)
date_ext = filter(lambda x: x.isdigit(), pretty_date)
#terminal logging
if stream_level:
ch = logging.StreamHandler()
ch.setLevel(stream_level)
ch.setFormatter(formatter)
#file logging
logname = ''.join([log.name, date_ext, '.log'])
fh = logging.FileHandler(os.path.join(log.dir, logname))
fh.setLevel(log.level)
fh.setFormatter(formatter)
logger.addHandler(fh)
if stream_level:
logger.addHandler(ch)
return logger
def hook(module_name):
"""pass in the special method __name__ for best results
don't call this until you've setup() the logger in your main function
"""
return logging.getLogger('.'.join([log.name,
First, the source:
log.py``
import datetime
import logging
import os
import config
#this is very straightforward, nothing special here.
log = config.Parser('log')
def setup(stream_level=logging.INFO):
"""shared log named {log.name + log.format}.log
call this logging setup method once, in the main function
always refer to the config file when referring to the logger
in modules other than the main file, call a reference to the
already created logger in memory via log.hook(module_name)
as long as this setup() was ran in the main method, the logfile
should already exist in the proper place, with streams created
for use, according to the config file entry for 'log'.
stream_level` indicates what level of detail should be printed to the terminal
"""
log.level = log.level.upper()
logger = logging.getLogger(log.name)
logger.setLevel(log.level)
formatter = logging.Formatter(log.format)
formatter.datefmt = log.datefmt
pretty_date = datetime.date.strftime(datetime.datetime.now(), log.datefmt)
date_ext = filter(lambda x: x.isdigit(), pretty_date)
#terminal logging
if stream_level:
ch = logging.StreamHandler()
ch.setLevel(stream_level)
ch.setFormatter(formatter)
#file logging
logname = ''.join([log.name, date_ext, '.log'])
fh = logging.FileHandler(os.path.join(log.dir, logname))
fh.setLevel(log.level)
fh.setFormatter(formatter)
logger.addHandler(fh)
if stream_level:
logger.addHandler(ch)
return logger
def hook(module_name):
"""pass in the special method __name__ for best results
don't call this until you've setup() the logger in your main function
"""
return logging.getLogger('.'.join([log.name,
Solution
You can find approach you are looking for in the logging cookbook and logging howto: Default logging module provides nice configuration feature.
So your code will be like this:
simpleExample.py (main):
util.py
And all the magic of logging configuration will be avalible in config file:
logging.cfg:
You can use any handlers you want, and you can change levels, formats etc and you don't have to change your code.
So your code will be like this:
simpleExample.py (main):
import os
import logging
import logging.config
logging.config.fileConfig(os.path.join(os.path.dirname(__file__),
'logging.conf')
import util
# create logger
logger = logging.getLogger("simpleExample")
# 'application' code
logger.info('starting now')
util.p()
logger.critical('quitting!')util.py
import logging
logger = logging.getLogger("simpleExample.Utils")
def p():
for x in range(10):
logger.warn('.')And all the magic of logging configuration will be avalible in config file:
logging.cfg:
[loggers]
keys=root,simpleExample
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=`You can use any handlers you want, and you can change levels, formats etc and you don't have to change your code.
Code Snippets
import os
import logging
import logging.config
logging.config.fileConfig(os.path.join(os.path.dirname(__file__),
'logging.conf')
import util
# create logger
logger = logging.getLogger("simpleExample")
# 'application' code
logger.info('starting now')
util.p()
logger.critical('quitting!')import logging
logger = logging.getLogger("simpleExample.Utils")
def p():
for x in range(10):
logger.warn('.')[loggers]
keys=root,simpleExample
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=`Context
StackExchange Code Review Q#18132, answer score: 4
Revisions (0)
No revisions yet.