1

I want my function do_x to use (child) logger __main__.do_all that is defined in the parent scope do_all from which do_x is called. Instead the root logger is used by default.

Is there a way do force do_x to use the child logger __main__.do_all? Should I pass the logger as parameter to do_x, even though it is not recommended in numerous posts? Assume that I want to call do_x also from other scopes using other (child) loggers.

import logging

logging.basicConfig(format='%(asctime)s - %(name)s - %(funcName)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

def do_x():
    logger.warning('doing x')

def do_all():
    logger = logging.getLogger(__name__ + '.do_all')
    logger.warning('Starting do_all')
    do_x()

def do_all_other():
    logger = logging.getLogger(__name__ + '.do_all_other')
    logger.warning('Starting do_all_other')
    do_x()

do_all()
do_all_other()

Produces

2022-09-27 11:34:40,562 - __main__.do_all - do_all - WARNING - Starting do_all
2022-09-27 11:34:40,562 - __main__ - do_x - WARNING - doing x
2022-09-27 11:34:40,562 - __main__.do_all_other - do_all_other - WARNING - Starting do_all_other
2022-09-27 11:34:40,562 - __main__ - do_x - WARNING - doing x

I want the second and the last line of the output to use __main__.do_all and __main__.do_all_other respectively

2
  • do_x() will need to know where it is called from. There is only two ways: pass the name of the parent as a param, or inspect the stack Commented Sep 26, 2022 at 15:24
  • No logger is really defined in the function. The call getLogger returns (creating if necessary) a specific logger instance that is managed by the logging module, regardless of where the call to getLogger is made. Commented Sep 26, 2022 at 18:38

2 Answers 2

2
import logging
import inspect

logging.basicConfig(format='%(asctime)s - %(name)s - %(funcName)s - %(levelname)s - %(message)s')

def do_x():
    logger_name = __name__ + '.' + inspect.stack()[1].function
    logger = logging.getLogger(logger_name)
    logger.warning('some log')

def do_all():
    do_x()

def do_other():
    do_x()


do_all()
do_other()

produces

2022-09-26 17:33:06,967 - __main__.do_all - do_x - WARNING - some log
2022-09-26 17:33:06,967 - __main__.do_other - do_x - WARNING - some log

Requires a recent version of python, but works with older versions too. inspect.stack() just returns the data in a slightly different format in older versions.

Sign up to request clarification or add additional context in comments.

Comments

0

The logger namespace is independent of function scopes. do_x should simply make the same call to getLogger to use the same Logger instance.

def do_x():
    logging.getLogger(__name__ + '.do_all').info('doing x')

3 Comments

It does not solve for possibility of "calling do_x from other scopes using other loggers". I updated the question a bit to illustrate this issue. Think of do_x as a general function called by various parent functions. Though thanks for the answer.
Why do you want to use the same logger if you want different output it?
I do not want to use same logger, I want exactly the opposite in fact. I was hoping that logger variable (is it variable?) in do_x can point to the Logger instance in the functions' parent scope, depending from where do_x is called. At the same time I want to keep the code for do_x general enough so that I do not have to edit it each time I add a new call with a new logger. Let's say that do_x is some simple transformation of data and I want to log some intermediary results on the way.

Your Answer

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.