4

I have various module files and want to share a common object (in this case a logger) to each of them. What is the best way to do this? I have a solution but it does not feel just right.

In pseudo code:

module_1.py

global logger
# module_1
def pass_logger_module1(plogger):
 global logger
 logger = plogger

module_2.py

global logger
# module_2
def pass_logger_module2(plogger):
 global logger
 logger = plogger

main_module.py

from module_1 import pass_logger_module1
from module_2 import pass_logger_module2
logger = set_logger(logfile, logformat, 'DEBUG')
pass_logger_module1(logger)
pass_logger_module2(logger)
asked Jul 19, 2018 at 13:34
3
  • 4
    That isn't how you should be using loggers. The logging module has the specific ability to define a parent logger with the settings you want and for child loggers to inherit them. You should read the documentation. Commented Jul 19, 2018 at 13:39
  • Thanks I will do. However in more general terms what is the best way to share a common object? Commented Jul 19, 2018 at 13:44
  • The best way is to pass it explicitly to each function that needs it and/or save it in objects that use it. Commented Jul 21, 2018 at 23:04

3 Answers 3

2

As pointed out in the comments this isn't the way use the logging module.

however a more general answer for "common object to different module files" is to do it the other way around from your example, meaning:

main_module.py

# this is in global
logger = set_logger(logfile, logformat, 'DEBUG')

module_1.py

from main_module import logger

module_2.py

from main_module import logger

EDIT: to avoid making a circular import perhaps store the logger in a different module:

settings.py

# this is in global
logger = set_logger(logfile, logformat, 'DEBUG')

main_module.py

from settings import logger
answered Jul 19, 2018 at 13:48
Sign up to request clarification or add additional context in comments.

3 Comments

this gives me circular import situation, but as suggested I can put the shared object in yet another module file and import from there...
Thanks that worked well. I had a setup module, however each module initiated its own instance of this setup, which worked ok for object that do not change in value, however I had my logger initiated several times. I have to rewrite it to make the setup object class objects and not instance objects...
It won't, You will get the same module that has already been imported (it will come from sys.modules). I encourage you check for yourself to see that it's true!
2

One way to do this is to expose your shared object through a third module, like so:

my_logger.py

logger = set_logger(logfile, logformat, 'DEBUG')

module_1.py

from my_logger import logger
...

module_2.py

from my_logger import logger
...

Your main module can then import both module_1 and module_2 without knowing about the logger and avoiding a circular import situation.

answered Jul 19, 2018 at 13:52

Comments

2

First, define your custom logger in custom_logger.py

import logging
import sys
class CustomFormatter(logging.Formatter):
 err_fmt = "[*] ERROR: %(msg)s"
 dbg_fmt = "[-] DEBUG: %(module)s: %(lineno)d: %(msg)s"
 info_fmt = "[+] %(msg)s"
 def __init__(self):
 super().__init__(fmt="%(levelno)d: %(msg)s", datefmt=None, style='%')
 def format(self, record):
 # Save the original format configured by the user
 # when the logger formatter was instantiated
 format_orig = self._style._fmt
 # Replace the original format with one customized by logging level
 if record.levelno == logging.DEBUG:
 self._style._fmt = CustomFormatter.dbg_fmt
 elif record.levelno == logging.INFO:
 self._style._fmt = CustomFormatter.info_fmt
 elif record.levelno == logging.ERROR:
 self._style._fmt = CustomFormatter.err_fmt
 # Call the original formatter class to do the grunt work
 result = logging.Formatter.format(self, record)
 # Restore the original format configured by the user
 self._style._fmt = format_orig
 return result
class CustomLogger(logging.Logger):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 formatter = CustomFormatter()
 handler = logging.StreamHandler(sys.stdout)
 handler.setFormatter(formatter)
 self.addHandler(handler)
 self.setLevel(logging.INFO)

Then, in your other modules, import CustomLogger.

from custom_logger import CustomLogger
logger = CustomLogger(__name__)
logger.debug("Hello, world!")
answered Jul 19, 2018 at 13:49

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.