averlon
averlon

Reputation: 347

python logging use two different loggers with different formatting

I am new to python!

I would like to setup two different loggers, both logging to stdout, but with different formats.

What I tried:

import logging

logging.basicConfig(
  level=logging.NOTSET,
  format='### %(levelname)-8s - %(message)s'
)

v_obj_CONSOLE = logging.StreamHandler()
v_obj_CONSOLE.setLevel(logging.NOTSET)
v_obj_FORMATTER = logging.Formatter(fmt='### %(name)s - %(asctime)s - %(levelname)-8s - %(message)s', datefmt='%d-%m-%Y %H:%M')
v_obj_CONSOLE.setFormatter(v_obj_FORMATTER)

logger1 = logging.getLogger('mylogger.1')
logger1.addHandler(v_obj_CONSOLE)

print()
print("from logging:")
logging.log(logging.INFO, 'started')

print()
logging.debug("test debug")
logging.info("test INFO")
logging.warning("test warning")
logging.error("test error")
logging.critical("test critical")

print()
print("from logger1:")
logger1.log(logging.INFO, 'started')

print()
logger1.debug("test debug")
logger1.info("test INFO")
logger1.warning("test warning")
logger1.error("test error")
logger1.critical("test critical")

Result is:

from logging:
### INFO     - started

### DEBUG    - test debug
### INFO     - test INFO
### WARNING  - test warning
### ERROR    - test error
### CRITICAL - test critical

from logger1:
### mylogger.1 - 24-02-2025 10:51 - INFO     - started
### INFO     - started

### mylogger.1 - 24-02-2025 10:51 - DEBUG    - test debug
### DEBUG    - test debug
### mylogger.1 - 24-02-2025 10:51 - INFO     - test INFO
### INFO     - test INFO
### mylogger.1 - 24-02-2025 10:51 - WARNING  - test warning
### WARNING  - test warning
### mylogger.1 - 24-02-2025 10:51 - ERROR    - test error
### ERROR    - test error
### mylogger.1 - 24-02-2025 10:51 - CRITICAL - test critical
### CRITICAL - test critical

As you see, for "logger1" I get the messages twice.

How can I avoid this and get the messages for "logger1" only in the second format I defined?

Update based on answer of @Hippolytehh

I changed in the proposed solution to :

logger1.setLevel(logging.NOTSET)
logger2.setLevel(logging.NOTSET)

complete code:

import logging

logger1 = logging.getLogger('logger1')
logger2 = logging.getLogger('mylogger.1')

handler1 = logging.StreamHandler()
handler2 = logging.StreamHandler()

formatter1 = logging.Formatter(fmt= '### %(levelname)-8s - %(message)s')
formatter2 = logging.Formatter(fmt='### %(name)s - %(asctime)s - %(levelname)-8s - %(message)s', datefmt='%d-%m-%Y %H:%M')

handler1.setFormatter(formatter1)
handler2.setFormatter(formatter2)

logger1.addHandler(handler1)
logger2.addHandler(handler2)

logger1.setLevel(logging.NOTSET)
logger2.setLevel(logging.NOTSET)

print()
print("from logging:")
logging.log(logging.INFO, 'started')

print()
logging.debug("test debug")
logging.info("test INFO")
logging.warning("test warning")
logging.error("test error")
logging.critical("test critical")

print()
print("from logger1:")
logger1.log(logging.INFO, 'started')

print()
logger1.debug("test debug")
logger1.info("test INFO")
logger1.warning("test warning")
logger1.error("test error")
logger1.critical("test critical")

print()
print("from logger2:")
logger2.log(logging.INFO, 'started')

print()
logger2.debug("test debug")
logger2.info("test INFO")
logger2.warning("test warning")
logger2.error("test error")
logger2.critical("test critical")

and got as a result:

from logging:

WARNING:root:test warning
ERROR:root:test error
CRITICAL:root:test critical

from logger1:

### WARNING  - test warning
WARNING:logger1:test warning
### ERROR    - test error
ERROR:logger1:test error
### CRITICAL - test critical
CRITICAL:logger1:test critical

from logger2:

### mylogger.1 - 24-02-2025 13:17 - WARNING  - test warning
WARNING:mylogger.1:test warning
### mylogger.1 - 24-02-2025 13:17 - ERROR    - test error
ERROR:mylogger.1:test error
### mylogger.1 - 24-02-2025 13:17 - CRITICAL - test critical
CRITICAL:mylogger.1:test critical

Upvotes: 0

Views: 47

Answers (1)

Hippolytehh
Hippolytehh

Reputation: 36

Duplication occurs because logging.basicConfig() sets a global configuration for the root logger. Since loggers propagate messages by default (propagate=True), messages from custom loggers also get logged by the root logger, leading to duplicates.

To fix this, you can:

  • Remove logging.basicConfig() and configure each logger individually, OR
  • Set propagate = False for each custom logger to prevent messages from being passed to the root logger.

Here's a working solution using the second option:

import logging

logging.basicConfig(level=logging.NOTSET)

logger1 = logging.getLogger('logger1')
logger2 = logging.getLogger('mylogger.1')

handler1 = logging.StreamHandler()
handler2 = logging.StreamHandler()

formatter1 = logging.Formatter(fmt= '### %(levelname)-8s - %(message)s')
formatter2 = logging.Formatter(fmt='### %(name)s - %(asctime)s - %(levelname)-8s - %(message)s', datefmt='%d-%m-%Y %H:%M')

handler1.setFormatter(formatter1)
handler2.setFormatter(formatter2)

logger1.addHandler(handler1)
logger2.addHandler(handler2)

logger1.setLevel(logging.NOTSET)
logger2.setLevel(logging.NOTSET)

logger1.propagate = False
logger2.propagate = False

print()
print("from logging:")
logger1.info('started')

print()
logger1.debug("test debug")
logger1.info("test INFO")
logger1.warning("test warning")
logger1.error("test error")
logger1.critical("test critical")

print()
print("from logger1:")
logger2.info('started')

print()
logger2.debug("test debug")
logger2.info("test INFO")
logger2.warning("test warning")
logger2.error("test error")
logger2.critical("test critical")

Which results in:

from logging:
### INFO     - started

### DEBUG    - test debug
### INFO     - test INFO
### WARNING  - test warning
### ERROR    - test error
### CRITICAL - test critical

from logger1:
### mylogger.1 - 24-02-2025 11:28 - INFO     - started

### mylogger.1 - 24-02-2025 11:28 - DEBUG    - test debug
### mylogger.1 - 24-02-2025 11:28 - INFO     - test INFO
### mylogger.1 - 24-02-2025 11:28 - WARNING  - test warning
### mylogger.1 - 24-02-2025 11:28 - ERROR    - test error
### mylogger.1 - 24-02-2025 11:28 - CRITICAL - test critical

Upvotes: 1

Related Questions