[python] 여러 모듈에서 로깅 사용

다음과 같은 구조의 작은 파이썬 프로젝트가 있습니다-

Project
 -- pkg01
   -- test01.py
 -- pkg02
   -- test02.py
 -- logging.conf

기본 로깅 모듈을 사용하여 stdout 및 로그 파일에 메시지를 인쇄하려고합니다. 로깅 모듈을 사용하려면 약간의 초기화가 필요합니다.

import logging.config

logging.config.fileConfig('logging.conf')
logger = logging.getLogger('pyApp')

logger.info('testing')

현재 메시지 로깅을 시작하기 전에 모든 모듈에서이 초기화를 수행합니다. 이 초기화를 한 곳에서 한 번만 수행하여 프로젝트 전체에 로깅하여 동일한 설정을 재사용 할 수 있습니까?



답변

모범 사례는 각 모듈에서 다음과 같이 로거를 정의하는 것입니다.

import logging
logger = logging.getLogger(__name__)

모듈 상단 근처에서 모듈의 다른 코드에서

logger.debug('My message with %s', 'variable data')

모듈 내에서 로깅 활동을 세분화해야하는 경우 다음을 사용하십시오.

loggerA = logging.getLogger(__name__ + '.A')
loggerB = logging.getLogger(__name__ + '.B')

과에 기록 loggerA하고 loggerB적절하게.

기본 프로그램에서 다음을 수행하십시오.

def main():
    "your program code"

if __name__ == '__main__':
    import logging.config
    logging.config.fileConfig('/path/to/logging.conf')
    main()

또는

def main():
    import logging.config
    logging.config.fileConfig('/path/to/logging.conf')
    # your program code

if __name__ == '__main__':
    main()

참조 여기에 여러 개의 모듈에서 로그온하고, 여기에 다른 코드에 의해 라이브러리 모듈로 사용되는 코드에 대한 로깅 구성.

업데이트 :을 호출 할 때 Python 2.6 이상을 사용 fileConfig()하고 있는지 지정할 disable_existing_loggers=False수 있습니다 (자세한 내용 은 문서 를 참조하십시오). 기본값은 True이전 버전과의 호환성을위한 것으로, 모든 로거가 fileConfig()해당 조상 또는 구성에서 명시 적으로 이름을 지정하지 않는 한 모든 로거가 비활성화됩니다 . 값을로 설정하면 False기존 로거가 그대로 유지됩니다. Python 2.7 / Python 3.2 이상을 사용하는 경우 구성을보다 잘 제어 할 수있는 dictConfig()것보다 더 나은 API 를 고려할 수 fileConfig()있습니다.


답변

실제로 모든 로거는 부모의 패키지 로거의 자식입니다 (즉 ,의 package.subpackage.module구성을 상속 package.subpackage)하므로 루트 로거를 구성하기 만하면됩니다).logging.config.fileConfig 대한 고유 한 구성) 또는 logging.basicConfig(루트 로거를 설정하여) . 사용자의 입력 모듈에서 설정 로깅 ( __main__.py또는 예를 들어, 실행 원하는대로 main_script.py.이 __init__.py뿐만 아니라 작동)

basicConfig 사용 :

# package/__main__.py
import logging
import sys

logging.basicConfig(stream=sys.stdout, level=logging.INFO)

fileConfig를 사용하여 :

# package/__main__.py
import logging
import logging.config

logging.config.fileConfig('logging.conf')

다음을 사용하여 모든 로거를 만듭니다.

# package/submodule.py
# or
# package/subpackage/submodule.py
import logging
log = logging.getLogger(__name__)

log.info("Hello logging!")

자세한 정보는 고급 로깅 ​​학습서를 참조하십시오 .


답변

나는 항상 아래와 같이합니다.

단일 파이썬 파일을 사용하여 내 로그를 ‘ log_conf.py‘ 라는 단일 패턴으로 구성하십시오.

#-*-coding:utf-8-*-

import logging.config

def singleton(cls):
    instances = {}
    def get_instance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return get_instance()

@singleton
class Logger():
    def __init__(self):
        logging.config.fileConfig('logging.conf')
        self.logr = logging.getLogger('root')

다른 모듈에서는 구성을 가져 오기만하면됩니다.

from log_conf import Logger

Logger.logr.info("Hello World")

이것은 간단하고 효율적으로 기록하는 단일 패턴입니다.


답변

이 답변 중 일부는 모듈 상단에서 수행하는 작업을 제안합니다.

import logging
logger = logging.getLogger(__name__)

이것이 매우 나쁜 관행으로 간주된다는 것이 나의 이해입니다 . 그 이유는 파일 구성이 기본적으로 모든 기존 로거를 비활성화하기 때문입니다. 예 :

#my_module
import logging

logger = logging.getLogger(__name__)

def foo():
    logger.info('Hi, foo')

class Bar(object):
    def bar(self):
        logger.info('Hi, bar')

그리고 메인 모듈에서 :

#main
import logging

# load my module - this now configures the logger
import my_module

# This will now disable the logger in my module by default, [see the docs][1] 
logging.config.fileConfig('logging.ini')

my_module.foo()
bar = my_module.Bar()
bar.bar()

기존의 로거가 fileconfig 호출에 의해 비활성화되었으므로 logging.ini에 지정된 로그가 비어 있습니다.

이 문제를 해결할 수는 있지만 (disable_existing_Loggers = False) 실제로 라이브러리의 많은 클라이언트는이 동작에 대해 알지 못하며 로그를받지 않습니다. 항상 logging.getLogger를 로컬로 호출하여 클라이언트가 쉽게 사용할 수 있도록하십시오. 모자 팁 : Victor Lin의 웹 사이트 에서이 동작에 대해 배웠습니다. .

따라서 항상 logging.getLogger를 로컬로 호출하는 것이 좋습니다. 예 :

#my_module
import logging

logger = logging.getLogger(__name__)

def foo():
    logging.getLogger(__name__).info('Hi, foo')

class Bar(object):
    def bar(self):
        logging.getLogger(__name__).info('Hi, bar')    

또한 기본에서 fileconfig를 사용하는 경우 라이브러리 디자이너가 모듈 레벨 로거 인스턴스를 사용하는 경우를 대비하여 disable_existing_loggers = False를 설정하십시오.


답변

여러 모듈에서 하나의 로깅 라이브러리 인스턴스를 사용하는 간단한 방법은 다음과 같은 해결책이었습니다.

base_logger.py

import logging

logger = logging
logger.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)

다른 파일들

from base_logger import logger

if __name__ == '__main__':
    logger.info("This is an info message")


답변

다른 해결책으로 던지기.

내 모듈의 init .py에는 다음과 같은 것이 있습니다.

# mymodule/__init__.py
import logging

def get_module_logger(mod_name):
  logger = logging.getLogger(mod_name)
  handler = logging.StreamHandler()
  formatter = logging.Formatter(
        '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
  handler.setFormatter(formatter)
  logger.addHandler(handler)
  logger.setLevel(logging.DEBUG)
  return logger

그런 다음 각 모듈에서 로거가 필요합니다.

# mymodule/foo.py
from [modname] import get_module_logger
logger = get_module_logger(__name__)

로그가 누락되면 해당 모듈에서 소스를 구별 할 수 있습니다.


답변

이와 같은 것을 생각 해낼 수도 있습니다!

def get_logger(name=None):
    default = "__app__"
    formatter = logging.Formatter('%(levelname)s: %(asctime)s %(funcName)s(%(lineno)d) -- %(message)s',
                              datefmt='%Y-%m-%d %H:%M:%S')
    log_map = {"__app__": "app.log", "__basic_log__": "file1.log", "__advance_log__": "file2.log"}
    if name:
        logger = logging.getLogger(name)
    else:
        logger = logging.getLogger(default)
    fh = logging.FileHandler(log_map[name])
    fh.setFormatter(formatter)
    logger.addHandler(fh)
    logger.setLevel(logging.DEBUG)
    return logger

위의 내용이 별도의 모듈에 정의되어 있고 다른 모듈로 가져온 경우 로깅이 필요한 경우 동일한 모듈과 전체 프로젝트에서 여러 로거를 사용할 수 있습니다.

a=get_logger("__app___")
b=get_logger("__basic_log__")
a.info("Starting logging!")
b.debug("Debug Mode")