HiveBrain v1.2.0
Get Started
← Back to all entries
principlepythonMinor

How's my approach to logging?

Submitted by: @import:stackexchange-codereview··
0
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: 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):

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.