Logging question

2 views
Skip to first unread message

Gabor Urban

unread,
Sep 23, 2009, 1:36:47 AM9/23/09
to python-list
Hi guys,

I have embarassing problem using the logging module. I would like to
encapsulate the creation and setting up of the logger in a class, but
it does not seem working.

Here are my relevant parts of the code:

--
import sys
import logging

class LogClass:
def __init__(self, fileName, loggerName = 'classLog'):
self.Logger = logging.getLogger(loggerName)
self.traceName = fileName
handler = logging.FileHandler(self.traceName,'a')
formatter = logging.Formatter("%(name)s %(asctime)s
%(filename)s %(lineno)d %(levelname)s %(message)s")
handler.setFormatter(formatter)
self.Logger.addHandler(handler)
self.Handler = handler

def closeLog(self):
self.Handler.flush()
self.Handler.close()

def fetchLogger(self):
return self.Logger

if __name__ == "__main__":
name = 'testlog.trc'
classLog = LogClass(name)
logger = classLog.fetchLogger()
logger.info("Created")
logger.debug("Test")
logger.info("Created .. ")
logger.debug("Test data")
classLog.closeLog()

--

The trace file is created properly but contains no lines at all. If I
put the code directly in __main__, it works fine.

What did I miss? Any ideas are wellcome.

Gabor
--
Linux: Choice of a GNU Generation

Diez B. Roggisch

unread,
Sep 23, 2009, 3:02:46 AM9/23/09
to
Gabor Urban schrieb:

That the default level is less than INFO - if you set that to e.g.
logging.DEBUG.

However, I think there are a few problems here beside that. For once,
reading PEP8 might be worth considering.

And the logging-module is written so that setting it up & using it are
de-coupled. Which you foil here somewhat. What is the above supposed to do?

Diez

Vinay Sajip

unread,
Sep 23, 2009, 7:49:12 AM9/23/09
to
On Sep 23, 6:36 am, Gabor Urban <urbang...@gmail.com> wrote:
> Hi guys,
>
> I have embarassing problem using theloggingmodule. I would like to

> encapsulate the creation and setting up  of the logger in a class, but
> it does not seem working.
>
> Here are my relevant parts of the code:
>
> --
[snip]

I'm not sure why you need to do this. Diez's reply tells you why you
don't see any output, but your code may also lead to other problems.
For example, if you create two LogClass instances with loggerName
values of "A" and "A.B", then any call to logger "A.B" will lead to
two messages in the log. That's because when a call to "A.B" is
handled, then it is passed to all handlers associated not only with
logger "A.B" but also "A" (its parent logger) and the root logger (its
grandparent). Since you have two FileHandlers configured (one for
"A.B" and one for "A"), the message will end up appearing in two files
(or the same file, if you used the same filename for both ClassLog
instantiations).

It's generally suspicious when you see someone trying to instantiate a
logger and adding a handler at the same time, as you're doing. The
reason this is a potential anti-pattern is that, other than for
trivial scripts, there isn't a natural one-to-one mapping between
loggers and handlers. Loggers (defined by their names, as in "A.B")
define areas of an application organized hierarchically (and answer
the question about a logging event, "Where did it happen?") whereas
handlers are about who's interested in those events, i.e. potential
log readers - they are generally organized according to the answer to
the question about a logging event, "Who wants to know?". In trivial
or command-line scripts, there's often just a one-to-one mapping (root
logger -> console) or one-to-two (root logger -> console and file) but
once your application gets more complex, then you usually have a good
few loggers (based on application areas) but just a few handlers (e.g.
one log file for everything, one log file for errors, console, and one
or two email handlers).

Regards,

Vinay Sajip

Jean-Michel Pichavant

unread,
Sep 23, 2009, 9:46:47 AM9/23/09
to Gabor Urban, python-list
Gabor Urban wrote:
> Hi guys,
>
> I have embarassing problem using the logging module. I would like to

> encapsulate the creation and setting up of the logger in a class, but
> it does not seem working.
>
> Here are my relevant parts of the code:
>
> --
> Gabor
>
As pointed out you should definitely split the logger creation from its
configuration, here are my 2 cents:

import logging

_LOGGER_NAME = 'foo'

class MyFileHandler(logging.FileHandler):
FORMAT = '%(name)s %(asctime)s %(filename)s %(lineno)d %(levelname)s
%(message)s'

def __init__(self, fileName):
logging.FileHandler.__init__(self, fileName, 'a')
self.setFormatter(logging.Formatter(self.FORMAT))

if __name__ == '__main__':
# split creation from configuration
# creation
logger = logging.getLogger(_LOGGER_NAME)
# configuration
logger.addHandler(MyFileHandler('anyfile.tmp'))
logger.setLevel(logging.DEBUG)
logger.info('bar')

I personally use the following pattern:

In any submodule moduleA.py of an application:

import MyApp
_logger = logging.getLogger(MyApp.logger.name + '.moduleA') # attach my
logger to MyApp logger
# Configuration : nothing to be done, relies on MyApp configuration logger

# You can add code in case you are executing your module in standalone
mode (for unit testing for instance)

if __name__ == '__main__':
_logger = logging.getLogger('moduleA')
_logger.addHandler(logging.FileHandler('moduleA.test','a'))
# here is some unit tests

Jean-Michel

Vinay Sajip

unread,
Sep 23, 2009, 9:59:32 AM9/23/09
to
On Sep 23, 2:46 pm, Jean-Michel Pichavant <jeanmic...@sequans.com>
wrote:

> I personally use the following pattern:
>
> In any submodule moduleA.py of an application:
>
> import MyApp
> _logger =logging.getLogger(MyApp.logger.name + '.moduleA') # attach my
> logger to MyApp logger

It's also common to use the pattern

logger = logging.getLogger(__name__)

which will use the name of the module for a logger name, correctly
getting the name of subpackages and submodules when used therein.

Regards,

Vinay Sajip

Reply all
Reply to author
Forward
0 new messages