표준 오류 스트림에서 로깅을 사용하지 않도록 설정하는 방법은 무엇입니까?
파이썬에서 표준 오류 스트림에 대한 로깅을 비활성화하는 방법은 무엇입니까?이것은 작동하지 않습니다.
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
그리고, 어떤 사람들에게는n
50 이상,
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
기본값); - 각 처리기에는 필터 목록이 있습니다.
로깅에는 다음 프로세스가 있습니다(플로우 차트로 표시됨).
따라서 특정 로거를 비활성화하려면 다음 전략 중 하나를 사용할 수 있습니다.
을 "" " " " " " 로거" 로 합니다.
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 } } })
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"] } } })
로거의 기존 핸들러를 제거하고 로거에 핸들러를 추가합니다(로거 및 해당 조상에서 핸들러를 찾을 수 없을 때 레코드가 핸들러로 전달되지 않도록 방지합니다).
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
'programing' 카테고리의 다른 글
Python에서 객체의 속성을 열거하는 방법은 무엇입니까? (0) | 2023.06.04 |
---|---|
특정 문자열을 포함하는 행 필터링 (0) | 2023.06.04 |
명령줄 인수를 RCMD BATCH에 전달하는 중 (0) | 2023.06.04 |
명령줄을 사용하여 postgres 백업 파일을 복원하시겠습니까? (0) | 2023.06.04 |
안드로이드에서 중력과 레이아웃 중력의 차이점은 무엇입니까? (0) | 2023.06.04 |