programing

표준 오류 스트림에서 로깅을 사용하지 않도록 설정하는 방법은 무엇입니까?

css3 2023. 6. 4. 22:27

표준 오류 스트림에서 로깅을 사용하지 않도록 설정하는 방법은 무엇입니까?

파이썬에서 표준 오류 스트림에 대한 로깅을 비활성화하는 방법은 무엇입니까?이것은 작동하지 않습니다.

import logging

logger = logging.getLogger()
logger.removeHandler(sys.stderr)
logger.warning('foobar')  # emits 'foobar' on sys.stderr

이에 대한 해결책을 찾았습니다.

logger = logging.getLogger('my-logger')
logger.propagate = False
# now if you use logger it will not log to console.

이렇게 하면 로그가 콘솔 로그를 포함하는 상위 로거로 전송되지 않습니다.

사용자:

logger = logging.getLogger()
logger.disabled = True
... whatever you want ...
logger.disabled = False

사용할 수 있는 항목:

logging.basicConfig(level=your_level)

여기서 your_level은 다음 중 하나입니다.

'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL

따라서_level logging으로 설정하면 됩니다.Critical. 다음 사람이 보낸 중요 메시지만 받게 됩니다.

logging.critical('This is a critical error message')

_수준 로깅으로 설정합니다.DEBUG는 모든 로깅 수준을 표시합니다.

자세한 내용은 로깅 예제를 참조하십시오.

각 처리기의 수준을 변경하는 것과 동일한 방법으로 처리기를 사용합니다.setLevel() 함수를 지정합니다.

import logging
import logging.handlers

LOG_FILENAME = '/tmp/logging_rotatingfile_example.out'

# Set up a specific logger with our desired output level
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)

# Add the log message handler to the logger
handler = logging.handlers.RotatingFileHandler(
          LOG_FILENAME, maxBytes=20, backupCount=5)

handler.setLevel(logging.CRITICAL)

my_logger.addHandler(handler)

컨텍스트 관리자 사용 - [가장 단순]

import logging 

class DisableLogger():
    def __enter__(self):
       logging.disable(logging.CRITICAL)
    def __exit__(self, exit_type, exit_value, exit_traceback):
       logging.disable(logging.NOTSET)

사용 예:

with DisableLogger():
    do_something()

[ 복잡한] 세분화된 솔루션이 필요한 경우 Advanced Logger를 확인할 수 있습니다.

AdvancedLogger can be used for fine grained logging temporary modifications

How it works:
Modifications will be enabled when context_manager/decorator starts working and be reverted after

Usage:
AdvancedLogger can be used
- as decorator `@AdvancedLogger()`
- as context manager `with  AdvancedLogger():`

It has three main functions/features:
- disable loggers and it's handlers by using disable_logger= argument
- enable/change loggers and it's handlers by using enable_logger= argument
- disable specific handlers for all loggers, by using  disable_handler= argument

All features they can be used together

Advanced Logger 사용 사례

# Disable specific logger handler, for example for stripe logger disable console
AdvancedLogger(disable_logger={"stripe": "console"})
AdvancedLogger(disable_logger={"stripe": ["console", "console2"]})

# Enable/Set loggers
# Set level for "stripe" logger to 50
AdvancedLogger(enable_logger={"stripe": 50})
AdvancedLogger(enable_logger={"stripe": {"level": 50, "propagate": True}})

# Adjust already registered handlers
AdvancedLogger(enable_logger={"stripe": {"handlers": "console"}

(오래된 질문이지만 미래의 검색자를 위한 질문)

원래 포스터의 코드/의도에 더 가까운 이것은 python 2.6에서 작동합니다.

#!/usr/bin/python
import logging

logger = logging.getLogger() # this gets the root logger

lhStdout = logger.handlers[0]  # stdout is the only handler initially

# ... here I add my own handlers 
f = open("/tmp/debug","w")          # example handler
lh = logging.StreamHandler(f)
logger.addHandler(lh)

logger.removeHandler(lhStdout)

logger.debug("bla bla")

내가 해결해야 할 gotcha는 새로운 것을 추가한 후 stdout 핸들러를 제거하는 것이었습니다; 로거 코드는 핸들러가 없으면 자동으로 stdout을 다시 추가하는 것처럼 보입니다.

IndexOutOfBound Fix: lhStdout을 인스턴스화하는 동안 IndexOfBound 오류가 발생하면 파일 핸들러를 추가한 후 인스턴스화를 로 이동합니다.

...
logger.addHandler(lh)

lhStdout = logger.handlers[0]
logger.removeHandler(lhStdout)

로깅을 완전히 비활성화하려면:

logging.disable(sys.maxint) # Python 2

logging.disable(sys.maxsize) # Python 3

로깅을 활성화하려면:

logging.disable(logging.NOTSET)

다른 답변은 다음과 같은 문제를 완전히 해결하지 못하는 해결 방법을 제공합니다.

logging.getLogger().disabled = True

그리고, 어떤 사람들에게는n50 이상,

logging.disable(n)

첫 번째 솔루션의 문제는 루트 로거에만 작동한다는 것입니다.를 들어, 다른로다같생이음성다니습었되과거는,▁using다gers▁other▁created니▁log를 사용하여 만든 다른 로거.logging.getLogger(__name__)이 방법으로 비활성화되지 않았습니다.

두 번째 솔루션은 모든 로그에 영향을 미칩니다.그러나 출력을 지정된 수준보다 높은 수준으로 제한하므로 50보다 큰 수준으로 로깅하여 출력을 재정의할 수 있습니다.

그것은 에 의해 예방될 수 있습니다.

logging.disable(sys.maxint)

(소스를 검토한 후) 내가 알기로는 로깅을 완전히 비활성화할 수 있는 유일한 방법입니다.

여기에 정말 좋은 답이 몇 가지 있지만, 가장 간단한 것은 (infinito에서만) 너무 많이 고려되지 않은 것 같습니다.

root_logger = logging.getLogger()
root_logger.disabled = True

그러면 루트 로거가 비활성화되고 다른 모든 로거가 비활성화됩니다.제가 테스트를 해본 적은 없지만 가장 빠를 것입니다.

python 2.7의 로깅 코드에서 나는 이것을 봅니다.

def handle(self, record):
    """
    Call the handlers for the specified record.

    This method is used for unpickled records received from a socket, as
    well as those created locally. Logger-level filtering is applied.
    """
    if (not self.disabled) and self.filter(record):
        self.callHandlers(record)

즉, 비활성화된 경우 핸들러가 호출되지 않으며, 매우 높은 값으로 필터링하거나 no-op 핸들러를 설정하는 것이 더 효율적입니다.

로깅의 구조는 다음과 같습니다.

  • 로거는 점 구분자가 있는 네임스페이스 계층에 따라 배열됩니다.
  • 각 로거에는 레벨(logging.WARNING 및 "" " "는 " " 입니다.logging.NOTSET비루트 로거의 경우 기본적으로) 및 유효 레벨(로거의 첫 번째 레벨과 조상이 다릅니다.logging.NOTSET,logging.NOTSET그렇지 않은 경우);
  • 각 로거에는 필터 목록이 있습니다.
  • 각 로거에는 핸들러 목록이 있습니다.
  • 각 핸들러에는 레벨(logging.NOTSET기본값);
  • 각 처리기에는 필터 목록이 있습니다.

로깅에는 다음 프로세스가 있습니다(플로우 차트로 표시됨).

로깅 흐름.

따라서 특정 로거를 비활성화하려면 다음 전략 중 하나를 사용할 수 있습니다.

  1. 을 "" " " " " " 로거" 로 합니다.logging.CRITICAL + 1.

    • 기본 API 사용:

      import logging
      
      logger = logging.getLogger("foo")
      logger.setLevel(logging.CRITICAL + 1)
      
    • config API 사용:

      import logging.config
      
      logging.config.dictConfig({
          "version": 1,
          "loggers": {
              "foo": {
                  "level": logging.CRITICAL + 1
              }
          }
      })
      
  2. lambda record: False벌목꾼에게

    • 기본 API 사용:

      import logging
      
      logger = logging.getLogger("foo")
      logger.addFilter(lambda record: False)
      
    • config API 사용:

      import logging.config
      
      logging.config.dictConfig({
          "version": 1,
          "filters": {
              "all": {
                  "()": lambda: (lambda record: False)
              }
          },
          "loggers": {
              "foo": {
                  "filters": ["all"]
              }
          }
      })
      
  3. 로거의 기존 핸들러를 제거하고 로거에 핸들러를 추가합니다(로거 및 해당 조상에서 핸들러를 찾을 수 없을 때 레코드가 핸들러로 전달되지 않도록 방지합니다).logging.StreamHandler가 있는 입니다.logging.WARNING에 방출되는 수준sys.stderr스트림) 및 로거의 속성을 로거의 조상 처리기에 레코드가 전달되지 않도록 설정합니다.

    • 기본 API 사용:

      import logging
      
      logger = logging.getLogger("foo")
      for handler in logger.handlers.copy():
          try:
              logger.removeHandler(handler)
          except ValueError:  # in case another thread has already removed it
              pass
      logger.addHandler(logging.NullHandler())
      logger.propagate = False
      
    • config API 사용:

      import logging.config
      
      logging.config.dictConfig({
          "version": 1,
          "handlers": {
              "null": {
                  "class": "logging.NullHandler"
              }
          },
          "loggers": {
              "foo": {
                  "handlers": ["null"],
                  "propagate": False
              }
          }
      })
      

경고.로거에 의해 기록되는 기록만 방지하는 전략 1 및 2와 반대로,logging.getLogger("foo")전략 3은 또한 로거의 후예(예: 로거의 후예)에 의해 기록되는 레코드를 로거의 핸들러와 그 조상에 의해 방출되는 것을 방지합니다.logging.getLogger("foo.bar")와 그됩니다. 로거의 핸들러와 그 조상들에 의해 배출됩니다.

참고 - 설정disabled은 의거속성입니다.True공개 API(cf)의 일부가 아니기 때문에 아직 다른 전략은 아닙니다.https://bugs.python.org/issue36318) :

import logging

logger = logging.getLogger("foo")
logger.disabled = True  # DO NOT DO THIS

stdout을 우회시킬 필요가 없습니다.더 나은 방법은 다음과 같습니다.

import logging
class MyLogHandler(logging.Handler):
    def emit(self, record):
        pass

logging.getLogger().addHandler(MyLogHandler())

더 간단한 방법은 다음과 같습니다.

logging.getLogger().setLevel(100)

이렇게 하면 여기에 설명된 대로 사용된 세 번째 라이브러리에서 모든 로깅이 차단됩니다. https://docs.python.org/3/howto/logging.html#configuring-logging-for-a-library

logging.getLogger('somelogger').addHandler(logging.NullHandler())
import logging

log_file = 'test.log'
info_format = '%(asctime)s - %(levelname)s - %(message)s'
logging.config.dictConfig({
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'info_format': {
            'format': info_format
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'info_format'
        },
        'info_log_file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'level': 'INFO',
            'filename': log_file,
            'formatter': 'info_format'
        }
    },
    'loggers': {
        '': {
            'handlers': [
                'console',
                'info_log_file'
            ],
            'level': 'INFO'
        }
    }
})


class A:

    def __init__(self):
        logging.info('object created of class A')

        self.logger = logging.getLogger()
        self.console_handler = None

    def say(self, word):
        logging.info('A object says: {}'.format(word))

    def disable_console_log(self):
        if self.console_handler is not None:
            # Console log has already been disabled
            return

        for handler in self.logger.handlers:
            if type(handler) is logging.StreamHandler:
                self.console_handler = handler
                self.logger.removeHandler(handler)

    def enable_console_log(self):
        if self.console_handler is None:
            # Console log has already been enabled
            return

        self.logger.addHandler(self.console_handler)
        self.console_handler = None


if __name__ == '__main__':
    a = A()
    a.say('111')
    a.disable_console_log()
    a.say('222')
    a.enable_console_log()
    a.say('333')

콘솔 출력:

2018-09-15 15:22:23,354 - INFO - object created of class A
2018-09-15 15:22:23,356 - INFO - A object says: 111
2018-09-15 15:22:23,358 - INFO - A object says: 333

test.log 파일 내용:

2018-09-15 15:22:23,354 - INFO - object created of class A
2018-09-15 15:22:23,356 - INFO - A object says: 111
2018-09-15 15:22:23,357 - INFO - A object says: 222
2018-09-15 15:22:23,358 - INFO - A object says: 333

사용자가 직접 핸들러를 작성했다고 가정하면 로거에 핸들러를 추가하기 직전에 다음 작업을 수행할 수 있습니다.

logger.removeHandler(logger.handlers[0])

그러면 기본 StreamHandler가 제거됩니다.이것은 파일에만 기록했어야 할 때 stderr로 로그가 불필요하게 방출된 후 Python 3.8에서 작동했습니다.

100% 해결책은 아니지만, 여기에 나와 있는 어떤 답변도 제 문제를 해결하지 못했습니다.심각도에 따라 색상이 지정된 텍스트를 출력하는 사용자 지정 로깅 모듈이 있습니다.로그가 중복되어 stdout 출력을 비활성화해야 했습니다.저는 거의 사용하지 않기 때문에 중요한 로그가 콘솔로 출력되는 것은 괜찮습니다.나는 그것을 내 로깅에 사용하지 않기 때문에 stderr 테스트를 하지 않았지만 stdout과 같은 방식으로 작업해야 합니다.STDout에 대해서만 CRITIAL을 최소 심각도로 설정합니다(요청된 경우 stderr).

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

# disable terminal output - it is handled by this module
stdout_handler = logging.StreamHandler(sys.stdout)

# set terminal output to critical only - won't output lower levels
stdout_handler.setLevel(logging.CRITICAL)

# add adjusted stream handler
logger.addHandler(stdout_handler)

로깅 모듈은 잘 모르지만 디버그(또는 정보) 메시지만 사용하지 않도록 설정하는 방식으로 사용하고 있습니다.사용할 수 있습니다.Handler.setLevel()로깅 수준을 Critical 이상으로 설정합니다.

또한 sys.stderr 및 sys.stdout을 쓰기 위해 열려 있는 파일로 바꿀 수 있습니다.http://docs.python.org/도서관/sys.html#sys.stdout 을 참조하십시오.하지만 저는 그것을 추천하지 않을 것입니다.

다음과 같은 작업도 수행할 수 있습니다.

handlers = app.logger.handlers
# detach console handler
app.logger.handlers = []
# attach
app.logger.handlers = handlers

"logging.config.dictConfig"에서 한 수준을 변경하면 전체 로깅 수준을 새로운 수준으로 전환할 수 있습니다.

logging.config.dictConfig({
'version': 1,
'disable_existing_loggers': False,
'formatters': {
    'console': {
        'format': '%(name)-12s %(levelname)-8s %(message)s'
    },
    'file': {
        'format': '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'
    }
},
'handlers': {
    'console': {
        'class': 'logging.StreamHandler',
        'formatter': 'console'
    },
#CHANGE below level from DEBUG to THE_LEVEL_YOU_WANT_TO_SWITCH_FOR
#if we jump from DEBUG to INFO
# we won't be able to see the DEBUG logs in our logging.log file
    'file': {
        'level': 'DEBUG',
        'class': 'logging.FileHandler',
        'formatter': 'file',
        'filename': 'logging.log'
    },
},
'loggers': {
    '': {
        'level': 'DEBUG',
        'handlers': ['console', 'file'],
        'propagate': False,
    },
}

})

데코레이터를 사용하여 우아한 솔루션을 찾았습니다. 이 솔루션은 다음과 같은 문제를 해결합니다. 만약 당신이 여러 개의 기능을 가진 모듈을 쓰고 있고, 각각 몇 개의 디버깅 메시지를 가지고 있으며, 당신이 현재 집중하고 있는 기능을 제외한 모든 기능에서 로깅을 비활성화하고 싶다면 어떻게 하시겠습니까?

장식기를 사용하여 이 작업을 수행할 수 있습니다.

import logging, sys
logger = logging.getLogger()
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)


def disable_debug_messages(func):
    def wrapper(*args, **kwargs):
        prev_state = logger.disabled
        logger.disabled = True
        result = func(*args, **kwargs)
        logger.disabled = prev_state
        return result
    return wrapper

그러면 다음을 수행할 수 있습니다.

@disable_debug_messages
def function_already_debugged():
    ...
    logger.debug("This message won't be showed because of the decorator")
    ...

def function_being_focused():
    ...
    logger.debug("This message will be showed")
    ...

전화를 해도function_already_debugged내부에서function_being_focused디버그 메시지function_already_debugged표시되지 않습니다.이렇게 하면 초점을 맞추고 있는 기능의 디버그 메시지만 볼 수 있습니다.

도움이 되길 바랍니다!

특정 처리기의 디버그 모드 수준을 완전히 비활성화하는 대신 변경할 수 있습니다.

따라서 사례가 있는 경우 콘솔에 대해서만 디버그 모드를 중지하고 오류와 같은 다른 수준을 유지해야 합니다.당신은 이것을 다음과 같이 할 수 있습니다.

# create logger
logger = logging.getLogger(__name__)

def enableConsoleDebug (debug = False):
    #Set level to logging.DEBUG to see CRITICAL, ERROR, WARNING, INFO and DEBUG statements
    #Set level to logging.ERROR to see the CRITICAL & ERROR statements only
    logger.setLevel(logging.DEBUG)

    debugLevel = logging.ERROR
    if debug:
        debugLevel = logging.DEBUG

    for handler in logger.handlers:
        if type(handler) is logging.StreamHandler:
            handler.setLevel (debugLevel)

그 이유는 사용자가 만든 모든 로거 때문입니다.

my_logger = logging.getLogger('some-logger')

루트 로거(로거와 함께 사용하는 로거)에 부모 필드/로그를 설정합니다.

root_logger = logging.getLogger()

방문하실 때

my_logger.debug('something')

로거의 모든 처리기와 로거의 상위 로거의 처리기를 (재귀적인 방식으로) 호출합니다.따라서 몇 마디로 루트 로거를 호출하여 std.err로 인쇄합니다.어떻게 해결합니까? 두 가지 솔루션, 글로벌:

root_logger = logging.getLogger()
# Remove the handler of root_logger making the root_logger useless
# Any logger you create now will have parent logger as root_logger but
# root_logger has been muted now as it does not have any handler to be called
root_logger.removeHandler(root_logger.handlers[0])

내가 선호하는 솔루션은 내 로거에 대해서만 루트 로거를 음소거하는 것입니다.

my_logger = logging.getLogger('some-logger')
my_logger.parent = None

.info, .vmdk 등을 호출할 때 호출되는 코드입니다. debug

당신의 로거의 모든 핸들러와 부모님 로거들을 어떻게 통과하는지 주목하세요.1766호선은 모선을 사용합니다.

일시적으로 비활성화할 핸들러의 하위 클래스:

class ToggledHandler(logging.StreamHandler):
"""A handler one can turn on and off"""

def __init__(self, args, kwargs):
    super(ToggledHandler, self).__init__(*args, **kwargs)
    self.enabled = True  # enabled by default

def enable(self):
    """enables"""
    self.enabled = True

def disable(self):
    """disables"""
    self.enabled = False

def emit(self, record):
    """emits, if enabled"""
    if self.enabled:
        # this is taken from the super's emit, implement your own
        try:
            msg = self.format(record)
            stream = self.stream
            stream.write(msg)
            stream.write(self.terminator)
            self.flush()
        except Exception:
            self.handleError(record)

이름으로 핸들러를 찾는 것은 매우 쉽습니다.

_handler = [x for x in logging.getLogger('').handlers if x.name == your_handler_name]
if len(_handler) == 1:
    _handler = _handler[0]
else:
    raise Exception('Expected one handler but found {}'.format(len(_handler))

한 번 찾은 경우:

_handler.disable()
doStuff()
_handler.enable()

언급URL : https://stackoverflow.com/questions/2266646/how-to-disable-logging-on-the-standard-error-stream