2013-07-19 4 views
6

라인을 인쇄하는 I가 다음 코드를파이썬 로깅 모듈은 여러 번

2013-07-19 17:42:02,657 INFO hey 
2013-07-19 17:42:02,657 INFO there 
2013-07-19 17:42:02,657 INFO there 

는 왜 두 번 "이"인쇄되는 :

import logging 
class A(object): 
    def __init__(self): 
     self._l = self._get_logger() 

    def _get_logger(self): 
     loglevel = logging.INFO 
     l = logging.getLogger(__name__) 
     l.setLevel(logging.INFO) 
     h = logging.StreamHandler() 
     f = logging.Formatter('%(asctime)s %(levelname)s %(message)s') 
     h.setFormatter(f) 
     l.addHandler(h) 
     l.setLevel(loglevel) 
     return l 

    def p(self, msg): 
     self._l.info(msg) 

for msg in ["hey", "there"]: 
    a = A() 
    a.p(msg) 

I는 얻을 출력? 마찬가지로 클래스 A의 다른 객체를 루프 안에 추가하고 메시지를 인쇄하면 세 번 인쇄됩니다.

로거의 이름이 일치하면 logging.getLogger()는 항상 동일한 로거 인스턴스를 반환합니다. 이 경우 이름이 일치하지 않습니다. 동일한 로거 인스턴스를 반환하지 않아야합니까? 그것이 사실이라면 왜 메시지가 여러 번 인쇄됩니까?

답변

12

로거가 한 번 생성되지만 여러 개의 처리기가 만들어집니다.

A을 한 번 생성하십시오. 다음과 같은

a = A() 
for msg in ["hey", "there"]: 
    a.p(msg) 

또는 변경 _get_logger :

def _get_logger(self): 
    loglevel = logging.INFO 
    l = logging.getLogger(__name__) 
    if not getattr(l, 'handler_set', None): 
     l.setLevel(logging.INFO) 
     h = logging.StreamHandler() 
     f = logging.Formatter('%(asctime)s %(levelname)s %(message)s') 
     h.setFormatter(f) 
     l.addHandler(h) 
     l.setLevel(loglevel) 
     l.handler_set = True 
    return l 
+0

사용 사례가 다릅니다. 자체 로거를 구현하는 클래스의 여러 객체를 생성 할 수 있기를 원합니다. 이것은 일을하는 올바른 방법입니까? 또한 로그 라인이 여러 번 인쇄되는 이유는 무엇입니까? –

+0

@NikhilSingh, 업데이트 된 설명 및 코드를 참조하십시오. – falsetru

+1

@NikhilSingh :'getLogger'는 매번 동일한 로거를 반환하지만,'A'를 인스턴스화 할 때마다 동일한 로거에서'addHandler'를 호출합니다. 추가 한 모든 핸들러에 대한 메시지가 인쇄됩니다. – geoffspear

4

내 경우는, 루트 로거 처리기라고도되고 있었다, 내가 한 모든 설정 propagate 로거 인스턴스의 속성을 False이었다.

import logging 
logger = logging.getLogger("MyLogger") 

# stop propagting to root logger 
logger.propagate = False 

# other log configuration stuff 
# ....