0

I'm triying to logging in python to two files from a settings.ini file, with differents levels but one of them, prints in boths files

I need to display error messages by console and two files:

  • ERROR level by console and log file
  • And INFO level only by file.

I read this previous posts:

Python logging to different destination using a configuration file

Python logging configuration file

Which were very useful. I tried defining a second logger and a second errorHandler, with class=FileHandler and args=('log_error','w') for the ERROR level, but it was the same result.

I think my problem is related with the propagates property according what the documentation says here https://docs.python.org/3/library/logging.config.html#configuration-file-format and like this says python logging to multiple destination but i have not find the error.

I tried setting propagate to False/0, but it didn't works.

  • Where is the error?
  • It is recommended to work each level with it's own each handle?
  • Can i do any other aditional improvement?

Thanks for your help

This is my main file:

from settings import *

def main():
#   logger.info("2")
    logger.error("4")

if __name__ == "__main__":
    main()

This is my settings.py file:

# -*- coding: utf-8 -*-
import os
import logging
import logging.config
from configparser import RawConfigParser

BASE_DIR = os.getcwd()
config = RawConfigParser()
config.read(BASE_DIR + '/settings.ini')

logging.config.fileConfig(fname=config, disable_existing_loggers=True)

# Create a custom logger
logger = logging.getLogger(__name__)

# Create handlers
handler_info = logging.FileHandler('log_info.log')
handler_error = logging.FileHandler('log_error.log')
handler_info.setLevel(logging.INFO)
handler_error.setLevel(logging.ERROR)

# Create formatters and add it to handlers
format_info = logging.Formatter('%(asctime)s - %(levelname)s - %(module)s : %(message)s')
format_error = logging.Formatter('%(asctime)s - %(levelname)s - %(module)s - %(lineno)d - %(message)s')
handler_info.setFormatter(format_info)
handler_error.setFormatter(format_error)

# Add handlers to the logger
logger.addHandler(handler_info)
logger.addHandler(handler_error)

And this is my settings.ini file:

[loggers]
keys=root

[handlers]
keys=consoleHandler

[formatters]
keys=sampleFormatter

[logger_root]
level=INFO
handlers=consoleHandler

[handler_consoleHandler]
class=StreamHandler
level=ERROR
formatter=sampleFormatter
args=(sys.stdout,)

[formatter_sampleFormatter]
format=%(asctime)s - %(levelname)s - %(message)s

When i print an INFO message everything is ok but when an error is printed, it writes the messages either log_error.log and log_info.log, and also by the console. I don't need to write in log_info.log if an error happend.

Manuel Carrero
  • 599
  • 1
  • 9
  • 29

1 Answers1

0

You can add a custom filter to your handler.

import logging

def custom_filter(record):
    if record.levelname == 'INFO':
        return True

handler = logging.StreamHandler()
handler.addFilter(custom_filter)

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)

logger.debug('1')
logger.info('2')
logger.error('3')

2

You can read the logging module source code, and easily to understand, only if custom_filter return a value can be converted to True, otherwise the log record will be ignored.

Yang HG
  • 710
  • 3
  • 18