Bruno Vermeulen
Bruno Vermeulen

Reputation: 3465

In Python how to pass a common object to different module files

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)

Upvotes: 4

Views: 1026

Answers (3)

moshevi
moshevi

Reputation: 6043

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

Upvotes: 2

Sean Pianka
Sean Pianka

Reputation: 2315

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!")

Upvotes: 2

Quinn Mortimer
Quinn Mortimer

Reputation: 721

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.

Upvotes: 2

Related Questions