1

I want to add a logging mechanism to my program. The basic structure of my project directory is so:

.
├── README.md
└── src
    ├── cli.py
    ├── module1.py
    ├── module2.py
    └── module3.py

cli.py imports all other module[1-3].py, but, I also use all other modules as independent executables by themselves (even outside the context of this project). I.e I use all of these commands:

$ python3 cli.py <args>
$ python3 module1.py
$ python3 module2.py <args>

The basic structure of the files:

# cli.py
import logging
from rich.logging import RichHandler
import module1

formatter = logging.Formatter('[%(asctime)s] %(levelname)s %(message)s')
file_handler = logging.FileHandler('cli.log')
file_handler.setFormatter(formatter)
console_handler = RichHandler()
log = logging.getLogger() # root handler
log.addHandler(file_handler)
log.addHandler(console_handler)

if __name__ == '__main__':
    log.error('Hi from cli.py')
    module1.foo()
# module1.py
import logging

log = logging.getLogger(__name__)
formatter = logging.Formatter('[%(asctime)s] %(levelname)s %(message)s')
file_handler = logging.FileHandler('module1.log')
file_handler.setFormatter(formatter)
log.addHandler(file_handler)


def foo():
    log.error('Hi from module1.py')

if __name__ == '__main__':
    foo()

Running results:

$ python3 cli.py
[12/14/21 11:29:05] ERROR    Hi from cli.py
                    ERROR    Hi from module1.py
$ python3 module1.py
Hi from module1.py

I wounder how can I configure logging so even when I'll execute $ python3 module1.py I'll still have the same formatting as defined in root (RichHandler). When I tried to just set an additional formatting inside module1.py, it resulted in a duplicated handler.
So basically I want to achieve this behavior:

$ python3 cli.py
[12/14/21 11:29:05] ERROR    Hi from cli.py      # also logged to cli.log
                    ERROR    Hi from module1.py  # also logged to cli.log and module1.log 
$ python3 module1.py
[12/14/21 11:29:05] ERROR    Hi from module1.py  # also logged to module1.log
Yair
  • 58
  • 6

1 Answers1

0

I believe I ran into the same issue recently. Within your import files, do not define "log".

Instead just import logging, and use, for example:

logging.error('Hi from module1.py')

This will then output as intended from the log object in cli.py.

Sam
  • 773
  • 4
  • 13