2011-05-12 4 views
33

나는 내장 된 logging을 사용하는 간단한 파이썬 스크립트를 가지고 있습니다.Python - 함수간에 로거 참조를 전달하지 않습니까?

로깅 기능을 구성하고 있습니다.

#!/usr/bin/env python 
import logging 
import ... 

def configure_logging(): 
    logger = logging.getLogger("my logger") 
    logger.setLevel(logging.DEBUG) 
    # Format for our loglines 
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") 
    # Setup console logging 
    ch = logging.StreamHandler() 
    ch.setLevel(logging.DEBUG) 
    ch.setFormatter(formatter) 
    logger.addHandler(ch) 
    # Setup file logging as well 
    fh = logging.FileHandler(LOG_FILENAME) 
    fh.setLevel(logging.DEBUG) 
    fh.setFormatter(formatter) 
    logger.addHandler(fh) 
    return logger 

def count_parrots(): 
    ... 
    logger.debug?? 

if __name__ == '__main__': 
    logger = configure_logging() 
    logger.debug("I'm a log file") 
    parrots = count_parrots() 

내가 내 __main__에서 로거 벌금을 호출 할 수 있습니다 : 기본 구조는 다음과 같은 것이다. 그러나 count_parrots() 함수 내부에서 logger를 호출하려면 어떻게해야합니까? 이렇게 로거를 구성하는 가장 무난한 방법은 무엇입니까?

답변

32

루트 (기본) 로거를 사용하면 모듈 레벨 기능 logging.debug을 사용할 수 있습니다. 또는이를 사용하는 기능에서 로거를 가져올 수 있습니다. 실제로 getLogger 함수는 레지스트리가있는 팩터 리 같은 함수 (싱글 톤과 유사)입니다. 즉, 지정된 로거 이름에 대해 항상 동일한 인스턴스를 반환합니다. 당신은, 따라서 단순히 처음에

logger = logging.getLogger("my logger") 

를 사용하여 count_parrots에서 로거를 얻을 수 있습니다. 그러나 규칙은 로거에 대해 점으로 구분 된 계층 적 이름을 사용하는 것입니다. 당신은 예를 들어, 개별 기능에 로깅 동작을 추가하는 장식을 사용할 수 있습니다

:

def debug(loggername): 
    logger = logging.getLogger(loggername) 
    def log_(enter_message, exit_message=None): 
     def wrapper(f): 
      def wrapped(*args, **kargs): 
       logger.debug(enter_message) 
       r = f(*args, **kargs) 
       if exit_message: 
        logger.debug(exit_message) 
       return r 
      return wrapped 
     return wrapper 
    return log_ 

my_debug = debug('my.logger') 

@my_debug('enter foo', 'exit foo') 
def foo(a, b): 
    return a+b 

당신은 로거 이름을 "하드 코딩"할 수 있고 리면를 제거 http://docs.python.org/library/logging.html#logging.getLogger

편집 참조 레벨 클로저와 my_debug.

+5

좋아요, 그래서 나는 logging.getLogger를 로깅 할 필요가있는 모든 함수의 시작 부분에서 호출 할 수 있습니다. 조금 낭비적이고 반복적 인 것 같습니다. 공정하다. 아니면 객체 지향적 인 것이 좋을까요? 전체적으로 많은 것을 클래스에 넣으려고합니까? (필자가 알고있는 매우 일반적인 질문이다, 나는 파이썬 세계에서 끝난 것이 무엇인지를 찾고있다). – victorhooi

+0

로거를 인스턴스 변수로 사용하여 클래스에 함수를 넣거나 (선호하는 경우) 개별 함수에 로깅 함수를 추가하는 데 데코레이터를 만들 수 있습니다. –

+9

이 대답은 파이썬의'logging' 모듈 ... – rkrzr

-3

count_parrots()에 대한 인수로 logger을 부여 할 수 있습니다. 또는 내가 할 수있는 것은 클래스 앵무새를 만들고 그 방법 중 하나로 로거를 사용하는 것입니다.

6

로깅을 처리하는 일반적인 방법은 모듈 별 로거를 전역 변수에 저장하는 것입니다. 그러면 해당 모듈 내의 모든 함수와 메소드가 동일한 로거 인스턴스를 참조합니다.

은 문서에서 사전 로깅 튜토리얼에 소개에서 간략하게 설명되어 있습니다 : http://docs.python.org/howto/logging.html#advanced-logging-tutorial

당신 패스 로거 매개 변수로 주위 인스턴스하지만, 이렇게하면 일반적으로 드물다.

+0

표준 연습은 logger = logging.getLogger ("logger.name")를 사용하는 것이라고 생각했습니다. –

+0

모듈 수준에서 확실히. 동일한 모듈에서 서로 다른 기능과 메소드에 대해 별도의 로거를 사용하는 것은 일반적으로 과잉입니다. 한 가지 예외는 별도의 로거를 사용하면 특정 이벤트를 기록하는 스레드를 기록하는 매우 쉬운 방법이 될 수 있다는 것입니다. – ncoghlan

+0

아. 나는 당신이 실제로'global' 키워드를 사용하는 것을 의미한다고 생각했습니다. –

13

당신은 다만 할 수 있습니다

logger = logging.getLogger("my logger") 

당신의 count_parrots() 방법. 이전에 사용 된 이름 (예 : "내 로거")을 전달하면 로깅 모듈은 해당 이름에 따라 생성 된 동일한 인스턴스를 반환합니다.

업데이트 : logging tutorial (emphais 광산)에서

getLogger()는 하지 만약이 제공되는 경우 지정된 이름을 가진 로거 인스턴스를 참조, 또는 루트를 반환합니다. 이름은 마침표로 계층 구조로 구분됩니다.복수 같은 이름을 사용하여 getLogger()를 호출하면 동일한 로거 개체에 대한 참조가 반환됩니다.

0

나는 전역 변수가 파이썬에서 어떻게 작동하는지 혼동했다. 함수 내에서 logger = logging.getLogger("my logger")과 같은 것을 수행하고 logger을 수정하려는 경우에만 global logger을 선언하면됩니다.

예제를 수정하려면 파일 시작 부분에 글로벌 로거 개체를 만들면됩니다. 모듈을 다른 모듈로 가져올 수있는 경우 NullHandler을 추가하여 라이브러리 가져 오기 기능을 활성화하지 않으려는 경우 라이브러리에 아무런 문제가 없습니다 (ref).

#!/usr/bin/env python 
import logging 
import ... 

logger = logging.getLogger("my logger").addHandler(logging.NullHandler()) 

def configure_logging(): 
    logger.setLevel(logging.DEBUG) 
    # Format for our loglines 
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") 
    # Setup console logging 
    ch = logging.StreamHandler() 
    ch.setLevel(logging.DEBUG) 
    ch.setFormatter(formatter) 
    logger.addHandler(ch) 
    # Setup file logging as well 
    fh = logging.FileHandler(LOG_FILENAME) 
    fh.setLevel(logging.DEBUG) 
    fh.setFormatter(formatter) 
    logger.addHandler(fh) 

def count_parrots(): 
    ... 
    logger.debug('counting parrots') 
    ... 
    return parrots 

if __name__ == '__main__': 
    configure_logging() 
    logger.debug("I'm a log file") 
    parrots = count_parrots() 
관련 문제