FAQ
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

Search Discussions

  • Diez B. Roggisch at Sep 23, 2009 at 7:02 am

    Gabor Urban schrieb:
    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.
    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 at Sep 23, 2009 at 11:49 am

    On Sep 23, 6:36?am, Gabor Urban 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 at Sep 23, 2009 at 1:46 pm

    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:

    --
    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
    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 at Sep 23, 2009 at 1:59 pm

    On Sep 23, 2:46?pm, Jean-Michel Pichavant 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

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedSep 23, '09 at 5:36a
activeSep 23, '09 at 1:59p
posts5
users4
websitepython.org

People

Translate

site design / logo © 2022 Grokbase