programing

Python Logging - 가져온 모듈에서 로깅 사용 안 함

padding 2023. 7. 12. 22:18
반응형

Python Logging - 가져온 모듈에서 로깅 사용 안 함

Python logging 모듈을 사용하고 있으며, 가져온 타사 모듈에서 출력하는 로그 메시지를 사용하지 않도록 설정하고 싶습니다.예를 들어 다음과 같은 것을 사용하고 있습니다.

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("내 메시지!")를 수행할 때 디버그 메시지가 출력되지만 가져온 모듈(예: 요청 및 기타 여러 가지)의 디버그 메시지도 출력됩니다.

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

이상적으로는 로거에게 "ModuleX, Module"에서 메시지를 인쇄하도록 지시할 수 있습니다.Y"하고 다른 모든 것을 무시합니다.

다음을 살펴보았지만 가져온 기능에 대한 모든 호출 전에 로깅을 비활성화/활성화할 필요는 없습니다. 로깅 - 가져온 모듈 로그를 무시하는 방법은 무엇입니까?

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

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

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

그러면 새 로거가 생성되므로 다른 모듈에 대한 로깅 수준이 실수로 변경되지 않습니다.


분히당신사합니다야용해은명합다니▁obviously를 사용해야 합니다.logger.debuglogging.debug후자는 다음을 호출하는 편의 함수이기 때문입니다.debug루트 로거의 메서드입니다.

이 문제는 고급 로깅 튜토리얼에 나와 있습니다.또한 간단한 방법으로 로그 메시지를 트리거한 모듈을 알 수 있습니다.

로깅 고급 튜토리얼과 문제 해결에서 매우 간단한 설명서를 따르긴 했지만 matplotlib에서 디버그 로그를 가져왔습니다.로거를 시작하고 있었어요main()다른 파일에서 플롯을 만드는 함수를 가져옵니다(내가 matplotlib를 가져온 위치).

제게 효과가 있었던 것은 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():
  ...

파이썬을 사용할 거라면logging패키지를 사용하는 모든 모듈에서 로거를 정의하는 것은 일반적인 관례입니다.

logger = logging.getLogger(__name__)

패키지가 이 규칙을 사용하는 경우 로거 이름이 패키지와 동일한 이름(또는 로거의 하위 이름)이기 때문에 로거에 대한 로깅을 활성화/비활성화하는 것이 쉽습니다.다른 로거와 동일한 파일에 기록할 수도 있습니다.

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)

이렇게 하면 외부 파일을 로드할 필요 없이 루트 로거를 사용하는 동안 가져온 모듈에서 만든 로거와 같은 기존의 모든 로거가 비활성화됩니다.

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

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

구성에 관련 옵션을 사용하는 보다 자세한 예는 https://gist.github.com/st4lk/6287746, 을 참조하십시오. 여기에서는 구성에 YAML을 사용하는 (일반적으로 작동하는) 예가 나와 있습니다.coloredlog도서관.

다음과 같은 방법을 사용할 수 있습니다.

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__그게 당신이 선호하는 방식이라면.

이 스레드와 다른 포럼에서 다양한 답변을 시도한 결과, 이 방법이 다른 모듈의 로거를 침묵시키는 데 효과적이라는 것을 알게 되었습니다.이는 다음 링크에서 영감을 얻었습니다.

https://kmasif.com/2019-11-12-ignore-logging-from-imported-module/

import logging
# Initialize your own logger
logger = logging.getLogger('<module name>')
logger.setLevel(logging.DEBUG)

# Silence other loggers
for log_name, log_obj in logging.Logger.manager.loggerDict.items():
     if log_name != '<module name>':
          log_obj.disabled = True

다른 모듈을 가져온 후 이 작업을 수행할 수 있습니다.그러나 다른 모듈의 로거를 비활성화할 수 있는 편리하고 빠른 방법을 찾았습니다.

@바쿠리우는 그 기능을 꽤 우아하게 설명합니다.반대로, 당신은 다음을 사용할 수 있습니다.getLogger()원하지 않는 로거를 검색 및 재구성하거나 비활성화하는 방법입니다.

나는 또한 추가하고 싶었습니다.logging.fileConfig()메서드는 다음 매개 변수를 수락합니다.disable_existing_loggers그러면 이전에 정의된 로거(가져온 모듈)가 비활성화됩니다.

@brendan의 대답에 영감을 받아 간단한 것을 만들었습니다.logger_blocklist레벨을 올리고 싶은 모든 로거를 사용할 수 있습니다.그래서 저는 그들 모두를 한꺼번에 침묵시킬 수 있었습니다.

import logging

logging.basicConfig(level=logging.DEBUG)

logger_blocklist = [
    "fiona",
    "rasterio",
    "matplotlib",
    "PIL",
]

for module in logger_blocklist:
    logging.getLogger(module).setLevel(logging.WARNING)

로의이에찾수있다습에서 수 .format="%(name)s" 변수, 매변수포, 함됨또에도 logging.basicConfig() 예:DEBUG:matplotlib.font_manager:findfont: score(FontEntry(fname='/usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf', name='Ubuntu', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05.

를 추가할 수 .matplotlib블록 목록으로 이동합니다.

@Finn의 대답과는 반대로, 그것을 밖에 둘 필요가 없었습니다.main() 타기.

이와 같은 작업을 수행하는 것만으로 문제가 해결됩니다.

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

참고: 이 줄을 어디에 두든지 프로젝트의 모든 위치에서 모든 가져오기가 해당 파일 자체 내에서 수행되는지 확인합니다.:)

저도 같은 문제가 있었습니다.저는 logging_config.py 파일을 가지고 있으며 이 파일은 다른 모든 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를 가져와 새 로거를 선언하고 레벨을 debug로 설정합니다.

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

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

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

예를 들어, 비누 호출을 처리하기 위한 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 이라는 모듈에 대한 로그를 생성합니다. 대량의 로그를 생성합니다.

enter image description here

로그 전파가 기본적으로 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)

가져온 모듈이 루트 로거를 사용하는 경우 필터(루트 로거의 https://docs.python.org/3/library/logging.html#filter-objects) 를 추가하여 원하지 않는 로그를 제거할 수 있습니다.

class FilterUnwantedRecords():
    def filter(self, record):
        if '3rdpartymodule' in record.pathname:
            return False
        return True

logging.getLogger().addFilter(FilterUnwantedRecords())

가져온 모듈 로거의 lvl을 debug < warning 또는 critical보다 높게 변경하기만 하면 됩니다.

# mymodule.py

# Import 'logging' module from standard library
import logging

# Set all loggers to show only WARNING and above
logging.basicConfig(level=logging.WARNING)

# Create your module-specific logger (__name__ will be 'mymodule' in this example)
logger = logging.getLogger(__name__)

# Set your desired logging level for your logger
logger.setLevel(level=logging.DEBUG)

# Add handlers if you want
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)

또 다른 예로, 이번에는 도우미 기능과 리치 타사 모듈의 리치 핸들러를 사용합니다.

# loghelper.py
import logging
from rich.logging import RichHandler

def new_logger(logger_name: str) -> logging.Logger:
    FORMAT = "%(message)s"
    logging.basicConfig(
        level=logging.WARNING, format=FORMAT, datefmt="[%X]", handlers=[RichHandler()]
    )
    log = logging.getLogger(logger_name)
    # Add handlers ...
    # ...
    return log

그런 다음 도우미 기능을 모듈로 가져옵니다.

# mymodule.py

from loghelper import new_logger

# Nice and tidy!
logger = new_logger(__name__)

언급URL : https://stackoverflow.com/questions/35325042/python-logging-disable-logging-from-imported-modules

반응형