Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change filehandle with Python logging on the fly with different classes and imports

I cannot perform an on-the-fly logging fileHandle change.

For example, I have 3 classes

one.py

import logging class One():     def __init__(self,txt="?"):         logging.debug("Hey, I'm the class One and I say: %s" % txt) 

two.py

import logging class Two():     def __init__(self,txt="?"):         logging.debug("Hey, I'm the class Two and I say: %s" % txt) 

config.py

import logging class Config():     def __init__(self,logfile=None):         logging.debug("Reading config")         self.logfile(logfile) 

myapp

from one import One from two import Two from config import Config import logging  #Set default logging logging.basicConfig(      level=logging.getLevelName(DEBUG),      format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',     filename=None )  logging.info("Starting with stdout")  o=One(txt="STDOUT") c=Config(logfile="/tmp/logfile")  # Here must be the code that change the logging configuration and set the filehandler  t=One(txt="This must be on the file, not STDOUT") 

If I try loggin.basicConfig() again, it doesn't work.

like image 529
xkill Avatar asked Dec 12 '12 12:12

xkill


People also ask

How do I create a multiple logging level in Python?

You can set a different logging level for each logging handler but it seems you will have to set the logger's level to the "lowest". In the example below I set the logger to DEBUG, the stream handler to INFO and the TimedRotatingFileHandler to DEBUG. So the file has DEBUG entries and the stream outputs only INFO.


2 Answers

Indeed, logging.basicConfig does nothing if a handler has been set up already:

This function does nothing if the root logger already has handlers configured for it.

You'll need to replace the current handler on the root logger:

import logging  fileh = logging.FileHandler('/tmp/logfile', 'a') formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fileh.setFormatter(formatter)  log = logging.getLogger()  # root logger for hdlr in log.handlers[:]:  # remove all old handlers     log.removeHandler(hdlr) log.addHandler(fileh)      # set the new handler 

See the Configuring Logging chapter in the Python Logging HOWTO.

like image 189
Martijn Pieters Avatar answered Oct 22 '22 08:10

Martijn Pieters


The answer provided by @Martijn Pieters works good. However, the code snipper removes all handlers and placed only the file handler back. This will be troublesome if your application has handlers added by other modules.

Hence, the below snippet is designed in such a way to replace only the file handler.

The line if isinstance(hdlr,logging.FileHandler) is the key.

import logging  filehandler = logging.FileHandler('/tmp/logfile', 'a') formatter = logging.Formatter('%(asctime)-15s::%(levelname)s::%(filename)s::%(funcName)s::%(lineno)d::%(message)s') filehandler.setFormatter(formatter) log = logging.getLogger()  # root logger - Good to get it only once. for hdlr in log.handlers[:]:  # remove the existing file handlers     if isinstance(hdlr,logging.FileHandler):         log.removeHandler(hdlr) log.addHandler(filehandler)      # set the new handler # set the log level to INFO, DEBUG as the default is ERROR log.setLevel(logging.DEBUG) 
like image 44
Arun Thundyill Saseendran Avatar answered Oct 22 '22 08:10

Arun Thundyill Saseendran