개발/Python

[파이썬] 아무것도 출력하지 않는 logging

MinorMan 2022. 10. 6. 01:36
반응형

<질문>

내가 쓰고 있는 파이썬 스크립트에서 로깅 모듈을 사용하여 이벤트를 기록하려고 합니다. 내 로거를 구성하는 다음 코드가 있습니다.

ERROR_FORMAT = "%(levelname)s at %(asctime)s in %(funcName)s in %(filename) at line %(lineno)d: %(message)s"
DEBUG_FORMAT = "%(lineno)d in %(filename)s at %(asctime)s: %(message)s"
LOG_CONFIG = {'version':1,
              'formatters':{'error':{'format':ERROR_FORMAT},
                            'debug':{'format':DEBUG_FORMAT}},
              'handlers':{'console':{'class':'logging.StreamHandler',
                                     'formatter':'debug',
                                     'level':logging.DEBUG},
                          'file':{'class':'logging.FileHandler',
                                  'filename':'/usr/local/logs/DatabaseUpdate.log',
                                  'formatter':'error',
                                  'level':logging.ERROR}},
              'root':{'handlers':('console', 'file')}}
logging.config.dictConfig(LOG_CONFIG)

내가 뛰려고 할 때logging.debug("Some string"), 콘솔에 출력을 얻지 못하더라도this page in the docs 말한다logging.debug 루트 로거가 메시지를 출력해야 합니다. 내 프로그램이 아무 것도 출력하지 않는 이유는 무엇이며 어떻게 고칠 수 있습니까?


<답변1>

수년이 지난 후에도 여전히 Python 로거에 사용성 문제가 있는 것 같습니다. 다음은 예시와 함께 몇 가지 설명입니다.

import logging
# This sets the root logger to write to stdout (your console).
# Your script/app needs to call this somewhere at least once.
logging.basicConfig()

# By default the root logger is set to WARNING and all loggers you define
# inherit that value. Here we set the root logger to NOTSET. This logging
# level is automatically inherited by all existing and new sub-loggers
# that do not set a less verbose level.
logging.root.setLevel(logging.NOTSET)

# The following line sets the root logger level as well.
# It's equivalent to both previous statements combined:
logging.basicConfig(level=logging.NOTSET)


# You can either share the `logger` object between all your files or the
# name handle (here `my-app`) and call `logging.getLogger` with it.
# The result is the same.
handle = "my-app"
logger1 = logging.getLogger(handle)
logger2 = logging.getLogger(handle)
# logger1 and logger2 point to the same object:
# (logger1 is logger2) == True

logger = logging.getLogger("my-app")
# Convenient methods in order of verbosity from highest to lowest
logger.debug("this will get printed")
logger.info("this will get printed")
logger.warning("this will get printed")
logger.error("this will get printed")
logger.critical("this will get printed")


# In large applications where you would like more control over the logging,
# create sub-loggers from your main application logger.
component_logger = logger.getChild("component-a")
component_logger.info("this will get printed with the prefix `my-app.component-a`")

# If you wish to control the logging levels, you can set the level anywhere 
# in the hierarchy:
#
# - root
#   - my-app
#     - component-a
#

# Example for development:
logger.setLevel(logging.DEBUG)

# If that prints too much, enable debug printing only for your component:
component_logger.setLevel(logging.DEBUG)


# For production you rather want:
logger.setLevel(logging.WARNING)

혼동의 일반적인 원인은 잘못 초기화된 루트 로거에서 비롯됩니다. 이걸 고려하세요:

import logging
log = logging.getLogger("myapp")
log.warning("woot")
logging.basicConfig()
log.warning("woot")

산출:

woot
WARNING:myapp:woot

런타임 환경 및 로깅 수준에 따라,기본 구성 이전의 첫 번째 로그 줄은 어디에도 표시되지 않을 수 있음.


<답변2>

기본 로깅 수준은 경고입니다. 레벨을 변경하지 않았기 때문에 루트 로거의 레벨은 여전히 경고입니다. 즉, 디버그 로깅을 포함하여 경고보다 낮은 수준의 로깅은 무시됩니다.

이것은tutorial:

import logging
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything

'info' 행은 정보보다 레벨이 높기 때문에 아무 것도 인쇄하지 않습니다.

레벨을 변경하려면 루트 로거에서 설정하면 됩니다.

'root':{'handlers':('console', 'file'), 'level':'DEBUG'}

다시 말해서 level=DEBUG로 핸들러를 정의하는 것만으로는 충분하지 않습니다. 실제 로깅 레벨도 DEBUG여야 무엇이든 출력할 수 있습니다.


<답변3>

여기에서 매우 간단한 답변을 원하는 모든 사람을 위해: 표시하려는 수준을 설정하기만 하면 됩니다. 내 모든 스크립트의 맨 위에 방금 넣었습니다.

import logging
logging.basicConfig(level = logging.INFO)

그런 다음 해당 수준 이상을 표시하려면 다음을 수행합니다.

logging.info("Hi you just set your fleeb to level plumbus")

로그가 설정한 수준으로 표시되도록 5가지 수준의 계층적 집합입니다.높게. 따라서 오류를 표시하려면 다음을 사용할 수 있습니다.logging.error("The plumbus is broken").

심각도가 높은 순서대로 수준은 다음과 같습니다.DEBUG,INFO,WARNING,ERROR, 그리고CRITICAL. 기본 설정은WARNING.

이것은 내 대답보다 더 잘 표현된 이 정보를 포함하는 좋은 기사입니다.
https://www.digitalocean.com/community/tutorials/how-to-use-logging-in-python-3


<답변4>

어쩌면 이것을 시도? 제 경우에는 모든 처리기를 제거한 후 문제가 해결된 것 같습니다.

for handler in logging.root.handlers[:]:
    logging.root.removeHandler(handler)

logging.basicConfig(filename='output.log', level=logging.INFO)

<답변5>

이 문제로 인해 많은 시간이 낭비되었으므로 답변을 작성하고 귀하의 답변을 저장하는 데 시간을 더 투자하겠습니다.

사용자 지정 로거에 대한 로깅 수준을 설정할 수 없습니다. (예: DEBUG 수준으로)

핸들러에 로깅 수준을 설정합니다.

import logging

# Get logger
logger = logging.getLogger("my logger")

# Create a handler and set logging level for the handler
c_handler = logging.StreamHandler()
c_handler.setLevel(logging.DEBUG) # <- Here things went wrong

# link handler to logger
logger.addHandler(c_handler)

# test
logger.debug('This is a debug message') # WILL NOT WORK

처리기 대신 로거 개체를 통해 로깅 수준 설정Customlogger.setLevel(logging.DEBUG)

import logging

# Get logger
logger = logging.getLogger("my logger")

# Create a handler
c_handler = logging.StreamHandler()

# link handler to logger
logger.addHandler(c_handler)

# Set logging level to the logger
logger.setLevel(logging.DEBUG) # <-- THIS!

# test
logger.debug('This is a debug message') # WILL WORK

<답변6>

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

이 코드는 기본 로깅 수준을 DEBUG로 설정합니다.


<답변7>

removeHandler() 함수를 호출하면 모든 핸들러가 제거된 경우에도 stdout/stderr 출력이 남습니다.

로거를 정리하는 한 가지 방법은 핸들러 목록을 비우는 것입니다. logger.handlers = [] 또는 logger.root.handlers = []

이것은 나를 위해 일했습니다.

반응형