Should a Python logger be passed as parameter?

2019-07-21 08:34发布

A Python application we're developing requires a logger. A coworker argues that the logger should be created and configured in every class that's using it. My opinion is that it should be created and configured on application start and passed as a constructor-parameter.

Both variants have their merits and we're unsure what the best practice is.

3条回答
叼着烟拽天下
2楼-- · 2019-07-21 09:04

Not usually; it is typically not meant to be passed as a parameter.

The convention is to use log = logging.getLogger(__name__) in the top of each module. The value of __name__ is different for each module. The resultant value of __name__ can then be reflected in each log message.

查看更多
唯我独甜
3楼-- · 2019-07-21 09:13

I think passing logger as parameter isn't good idea. You should consider a global logger as own module, it would be the best idea. For example:
logger.py

import logging
log = logging.getLogger('')

classFoo.py

form logger import log
log.debug('debug message')

classBar.py

form logger import log
log.warn('warn!')
查看更多
爷的心禁止访问
4楼-- · 2019-07-21 09:16

Maybe this helps you to get an idea? Of course you can make it much better, reading settings from a config file or whatever but this is quick example.

A separate module to configure the logging: mylogmod.py :

import logging

FILENAME = "mylog.log" # Your logfile
LOGFORMAT = "%(message)s" # Your format
DEFAULT_LEVEL = "info" # Your default level, usually set to warning or error for production
LEVELS = {
    'debug':logging.DEBUG,
    'info':logging.INFO,
    'warning':logging.WARNING,
    'error':logging.ERROR,
    'critical':logging.CRITICAL}

def startlogging(filename=FILENAME, level=DEFAULT_LEVEL):
    logging.basicConfig(filename=filename, level=LEVELS[level], format=LOGFORMAT)

The main.py :

import logging
from mylogmod import startlogging
from myclass import MyClass

startlogging()

logging.info("Program started...")
mc = MyClass()

A class myclass.py from a module with self test. You can do something similar in a unittest: (Note that you don't need to import the logging module in a unittest, just the startlogging function is enough. This way you can set the default level to warning or error and the unittests and self tests to debug)

import logging

class MyClass(object):
    def __init__(self):
        logging.info("Initialze MyClass instance...")

if __name__ == "__main__":
    from mylogmod import startlogging
    startlogging(level="debug")
    logging.debug("Test MyClass...")
    #... rest of test code...
查看更多
登录 后发表回答