Python 로깅-가져온 모듈에서 로깅 비활성화


100

Python 로깅 모듈을 사용하고 있으며 가져 오는 타사 모듈에서 인쇄 한 로그 메시지를 비활성화하고 싶습니다. 예를 들어 다음과 같은 것을 사용하고 있습니다.

logger = logging.getLogger()
logger.setLevel(level=logging.DEBUG)
fh = logging.StreamHandler()
fh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s')
fh.setFormatter(fh_formatter)
logger.addHandler(fh)

이렇게하면 logger.debug ( "my message!")를 수행 할 때 디버그 메시지가 출력되지만 내가 가져온 모듈 (예 : 요청 및 기타 여러 가지)의 디버그 메시지도 출력합니다.

관심있는 모듈의 로그 메시지 만보고 싶습니다. 로깅 모듈이이 작업을 수행하도록 할 수 있습니까?

이상적으로는 로거에게 "ModuleX, ModuleY"의 메시지를 인쇄하고 다른 모든 메시지는 무시하도록 지시하고 싶습니다.

다음을 살펴 보았지만 가져온 함수를 호출 할 때마다 로깅을 비활성화 / 활성화 할 필요가 없습니다. 로깅-가져온 모듈 로그를 무시하는 방법?

답변:


69

문제는 getLogger인수없이 호출 하면 루트 로거가 반환 되므로 레벨을 설정할 때 logging.DEBUG해당 로거를 사용하는 다른 모듈의 레벨도 설정됩니다.

루트 로거를 사용 하지 않음 으로써이 문제를 해결할 수 있습니다 . 이렇게하려면 모듈 이름과 같이 이름을 인수로 전달하면됩니다.

logger = logging.getLogger('my_module_name')
# as before

이렇게하면 새 로거가 생성되므로 다른 모듈의 로깅 수준이 실수로 변경되지 않습니다.


후자는 루트 로거 의 메서드 를 호출하는 편리한 함수이기 때문에 분명히 logger.debug대신 사용해야 합니다 .logging.debugdebug

이것은 고급 로깅 ​​자습서에 언급되어 있습니다. 또한 간단한 방법으로 어떤 모듈이 로그 메시지를 트리거했는지 알 수 있습니다.


37
__name__r 로 로거를 만들고 있지만 가져온 모듈의 로그가 계속 표시됩니다. ini 구성 파일로 로깅을 구성하려고하는데 어떻게해야합니까?
Durga Swaroop

8
로거를 만드는 __name__것도 저에게 효과적이지 않았습니다. "모듈"이 아닌 독립 실행 형 스크립트를 사용하고 있기 때문일까요? 나를 위해 일한 것은 가져온 모듈 ( matpplotlib내 경우에는)에 대한 로깅을 구성 logging.getLogger("matplotlib").setLevel(logging.WARNING)하고 logging.basicConfig.
bli

1
"분명히 " logger.debug대신 사용해야 합니다 logging.debug. "라는 문구의 가치를 강조하고 싶었습니다 . 로거 대신 로깅 을 사용하는 것은 쉬운 실수 이지만 설정하려는 모든 영리한 구성을 사용하지 않습니다. 나는 지난 몇 시간 동안 이것을 살았습니다!
timdadev

@bli 라이브러리를 개발할 때와 실행 파일을 개발할 때 로깅에는 큰 차이가 있습니다. 기본적으로 : 가져올 모듈 / 패키지를 작성하는 경우 아무것도 구성 하지 않아야 합니다. 모듈은 로깅 수준이나 처리기를 구성하지 않고 logger = logging.getLogger('package.my_module')및 your could 호출 만 포함해야합니다 logger.debug/warning. 당신은 바이너리 응용 프로그램을 작성하는 경우 당신은 다양한 로그 및 핸들러의 수준을 결정해야합니다. 로깅 구성이 포함 된 라이브러리는 항상 문제가됩니다.
Bakuriu

필자의 경우 가져온 패키지는 루트 로거 (를 통해 logging.info)를 사용합니다. 이 패키지에서 루트 로그를 특별히 비활성화하는 방법이 있습니까?
IanS

45

파이썬 logging패키지 를 사용하려는 경우이를 사용하는 모든 모듈에서 로거를 정의하는 것이 일반적인 규칙입니다.

logger = logging.getLogger(__name__)

많은 인기있는 파이썬 패키지가이를 수행합니다 requests. 패키지가이 규칙을 사용하는 경우 로거 이름이 패키지와 동일한 이름 (또는 해당 로거의 하위)이되기 때문에 로깅을 활성화 / 비활성화하기가 쉽습니다. 다른 로거와 동일한 파일에 기록 할 수도 있습니다.

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

requests_logger = logging.getLogger('requests')
requests_logger.setLevel(logging.DEBUG)

handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
requests_logger.addHandler(handler)

15
logging.basicConfig(...)모든 로거 를 사용하여 공식 기본 자습서에서와 같이 로거를 구성하려고 할 때 logging.lastResort핸들러가 지정되지 않은 경우 (stderr 인 Python 3.2로 시작) 또는 설정 한 핸들러로 출력됩니다. 따라서 사용하지 마십시오. 그렇지 않으면 어쨌든 모든 로그 메시지를 계속 받게됩니다.
user136036

43

이것이 게시하기에 적절한 지 확실하지 않지만 오랫동안 갇혀 있었고 다른 곳에서는 찾지 못했기 때문에 동일한 문제를 가진 사람을 돕고 싶었습니다!

로깅 고급 자습서문제 해결 에서 매우 간단한 설명서를 따랐음에도 불구하고 matplotlib에서 디버그 로그를 얻었습니다 . main()한 파일 에서 로거를 시작 하고 다른 파일에서 플롯을 생성하는 함수를 가져 왔습니다 (matplotlib를 가져온 곳).

나를 위해 일한 것은 내 주 파일의 다른 모듈에서와 마찬가지로 matplotlib 가져 오기 전에 수준을 설정하는 것이 었습니다. 이것은 나에게 반 직관적 인 것처럼 보였으므로 아직 가져 오지 않은 로거에 대한 구성을 설정할 수있는 방법에 대한 통찰력이있는 사람이 있다면 이것이 어떻게 작동하는지 궁금 할 것입니다. 감사!

내 주 파일에서 :

import logging
import requests
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logging.getLogger('requests').setLevel(logging.DEBUG)

def main():
  ...

plot.py파일에서 :

import logging
logging.getLogger('matplotlib').setLevel(logging.WARNING)
import matplotlib.pyplot as plt

def generatePlot():
  ...

오류가 발생했습니다 : 'Logger'개체에 'DEBUG'속성이 없습니다. logger.DEBUG이어야합니다logging.DEBUG
foxiris 19 년

감사! 정말 도움이됩니다! 기본 로깅 구성 후 matplotlib를 가져올 명령 전에 matplotlib 로깅 수준을 설정했습니다. 해결되었습니다!
gph

나는에 대한 로깅을 설정 한 matplotlibWARNING 나는 보풀이 오류를 줄 것이다 가져 오기 전에를 추가하기 때문에, 모듈을 가져온. 그것은 여전히 ​​나를 위해 일했습니다. matplotlib==3.3.2도움이된다면 Python 3.7에서 사용 하고 있습니다.
End-2-End

9

@Bakuriu는 기능을 아주 우아하게 설명합니다. 반대로,이 getLogger()방법을 사용하여 원하지 않는 로거를 검색하고 재구성 / 비활성화 할 수 있습니다 .

또한 이전에 정의 된 로거 (즉, 가져온 모듈에서)를 비활성화 logging.fileConfig()하는 매개 변수를 허용하는 메서드 를 추가하고 싶었습니다 disable_existing_loggers.


9

이렇게하면 루트 로거를 계속 사용하는 동안 (외부 파일을로드 할 필요없이) 가져온 모듈에 의해 생성 된 것과 같은 기존의 모든 로거가 비활성화됩니다.

logging.config.dictConfig({
    'version': 1,
    'disable_existing_loggers': True,
})

먼저 기록하고 싶지 않은 모든 모듈을 가져와야합니다! 그렇지 않으면 "기존 로거"로 간주되지 않습니다. 그런 다음 해당 모듈의 모든 로거를 비활성화합니다. 이로 인해 중요한 오류를 놓칠 수도 있습니다!

구성에 관련 옵션을 사용하는 자세한 예제는 https://gist.github.com/st4lk/6287746을 참조 하십시오 . 여기 에는 coloredlog라이브러리 구성에 YAML을 사용하는 (부분적으로 작동하는) 예제가 있습니다.


질문이 뭐야?
user1767754

1
request예를 들어 작동 하지만 가져온 모듈이 나중에 호출 할 클래스 내에 로거를 만들 때 작동 APScheduler하지 않습니다.BackgroundScheduler.BackgroundScheduler() . 솔루션을 보려면 여기를 참조하십시오. stackoverflow.com/a/48891485/2441026
user136036

이것은 yaml 구성 파일을 사용하는 제 경우에서 작동합니다
user4015990

4

다음과 같이 사용할 수 있습니다.

logging.getLogger("imported_module").setLevel(logging.WARNING)
logging.getLogger("my_own_logger_name").setLevel(logging.DEBUG)

이렇게하면 내 모듈의 로그 수준이 DEBUG로 설정되고 가져온 모듈이 동일한 수준을 사용하지 못합니다.

참고 : "imported_module"교체 할 수 있습니다 imported_module.__name__(따옴표없이)을 "my_own_logger_name"대체 할 수 __name__그건 당신이 그것을 할 선호하는 방법입니다 경우.


1

나는 같은 문제가 있었다. 다른 모든 py 파일에서 가져 오는 logging_config.py 파일이 있습니다. logging_config.py 파일에서 루트 로거 로깅 수준을 ERROR로 설정했습니다 (기본적으로 경고).

logging.basicConfig(
    handlers=[
        RotatingFileHandler('logs.log',maxBytes=1000, backupCount=2),
        logging.StreamHandler(), #print to console
    ],
    level=logging.ERROR
)

다른 모듈에서는 logging_config.py를 가져오고 새 로거를 선언하고 디버그 수준을 설정합니다.

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)

이렇게하면 내 py 파일에 로그인하는 모든 것이 기록되지만 urllib, request, boto3 등과 같은 가져온 모듈에 의해 디버그 및 정보 수준에서 기록 된 내용은 기록되지 않습니다. 가져 오기 모듈에 오류가 있으면 루트 로거 수준을 ERROR로 설정했기 때문에 로깅됩니다.


0

고려해야 할 또 다른 사항은 Logger 클래스 의 propagate 속성입니다.

예를 들어, SOAP 호출을 처리하기위한 py-suds 라이브러리, 심지어 ERROR

logging.getLogger('suds.client').setLevel(logging.ERROR)
logging.getLogger('suds.transport').setLevel(logging.ERROR)
logging.getLogger('suds.xsdschema').setLevel(logging.ERROR)
logging.getLogger('suds.wsdl').setLevel(logging.ERROR)

sxbasics.py라는 모듈에 대한 로그 로그 생성 g 엄청난 양의 로그

여기에 이미지 설명 입력

로그 전파는 기본적으로 True이고 False로 설정되어 있기 때문에 514MB의 로그를 복구했습니다.

import logging
logging.getLogger("suds").propagate = False
logging.getLogger('suds.client').setLevel(logging.ERROR)
logging.getLogger('suds.transport').setLevel(logging.ERROR)
logging.getLogger('suds.xsdschema').setLevel(logging.ERROR)
logging.getLogger('suds.wsdl').setLevel(logging.ERROR)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.