我正在使用Python的logging模块,我想暂时禁用控制台日志记录,但它不起作用。
#!/usr/bin/python
import logging
logger = logging.getLogger() # this gets the root logger
# ... here I add my own handlers
#logger.removeHandler(sys.stdout)
#logger.removeHandler(sys.stderr)
print logger.handlers
# this will print [<logging.StreamHandler instance at ...>]
# but I may have other handlers there that I want to keep
logger.debug("bla bla")
上面的代码在stdout上显示bla bla
,我不知道如何安全地禁用控制台处理程序。我如何确定暂时删除控制台StreamHandler而不是另一个?
答案 0 :(得分:174)
我找到了解决方案:
logger = logging.getLogger('my-logger')
logger.propagate = False
# now if you use logger it will not log to console.
这将阻止将日志记录发送到包含控制台日志记录的上部记录程序。
答案 1 :(得分:79)
我用:
logger = logging.getLogger()
logger.disabled = True
... whatever you want ...
logger.disabled = False
答案 2 :(得分:60)
您可以使用:
logging.basicConfig(level=your_level)
其中 your_level 就是其中之一:
'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL
因此,如果您将 your_level 设置为 logging.CRITICAL ,您将只收到以下发送的重要消息:
logging.critical('This is a critical error message')
将 your_level 设置为 logging.DEBUG 会显示所有级别的日志记录。
有关详细信息,请查看logging examples.
以相同的方式更改每个处理程序使用Handler.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)
答案 3 :(得分:43)
(长期存在的问题,但未来的搜索者)
更接近原始海报的代码/意图,这适用于我在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")
我必须解决的问题是在添加一个新的之后删除stdout处理程序;如果没有处理程序,则记录器代码似乎会自动重新添加标准输出。
答案 4 :(得分:35)
上下文管理器
import logging
class DisableLogger():
def __enter__(self):
logging.disable(logging.CRITICAL)
def __exit__(self, a, b, c):
logging.disable(logging.NOTSET)
使用示例:
with DisableLogger():
do_something()
答案 5 :(得分:25)
这里有一些非常好的答案,但显然最简单的是没有考虑太多(仅限于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)
这意味着当它被禁用时,不会调用任何处理程序,例如,过滤到非常高的值或设置无操作处理程序应该更有效。
答案 6 :(得分:22)
完全禁用日志记录:
logging.disable(sys.maxint) # Python 2
logging.disable(sys.maxsize) # Python 3
启用日志记录:
logging.disable(logging.NOTSET)
其他答案提供的工作无法完全解决问题,例如
logging.getLogger().disabled = True
,对于大于50的某些n
,
logging.disable(n)
第一个解决方案的问题是它只适用于根记录器。使用,例如logging.getLogger(__name__)
创建的其他记录器不会被此方法禁用。
第二个解决方案会影响所有日志。但它将输出限制在高于给定值的水平,因此可以通过以大于50的水平记录来覆盖它。
可以通过
来预防logging.disable(sys.maxint)
据我所知(在审核source之后)是完全禁用日志记录的唯一方法。
答案 7 :(得分:10)
无需转移标准输出。这是更好的方法:
import logging
class MyLogHandler(logging.Handler):
def emit(self, record):
pass
logging.getLogger().addHandler(MyLogHandler())
更简单的方法是:
logging.getLogger().setLevel(100)
答案 8 :(得分:5)
日志记录中有the following structure:
logging.WARNING
,对于非根记录器默认为logging.NOTSET
)和有效级别 em>(父记录器对级别为logging.NOTSET
的非root记录器的有效级别,否则为记录器的级别)logging.NOTSET
)
日志记录中有the following process(以流程图表示):
因此,要禁用特定的记录器,您可以执行以下操作之一:
将记录器的级别设置为logging.CRITICAL + 1
。
使用主要API:
import logging
logger = logging.getLogger("foo")
logger.setLevel(logging.CRITICAL + 1)
使用配置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)
使用配置API:
import logging.config
logging.config.dictConfig({
"version": 1,
"filters": {
"all": {
"()": lambda: (lambda record: False)
}
},
"loggers": {
"foo": {
"filters": ["all"]
}
}
})
删除记录器的现有处理程序add a handler logging.NullHandler()
to the logger(以防止使用当前流{{1}的logging.lastResort
处理程序logging.StreamHandler
处理事件) }和级别sys.stderr
和set the attribute propagate
of the logger to False
(以防止事件由记录器的祖先记录器的处理程序处理)。
使用主要API:
logging.WARNING
使用配置API:
import logging
logger = logging.getLogger("foo")
for handler in logger.handlers.copy():
logger.removeHandler(handler)
logger.addHandler(logging.NullHandler())
logger.propagate = False
警告。 —与方法1和2相反,方法1和方法2仅阻止记录器 记录的事件及其记录祖先的处理程序发出,方法3还可以防止由记录器的后代记录器 记录的事件(例如import logging.config
logging.config.dictConfig({
"version": 1,
"handlers": {
"null": {
"class": "logging.NullHandler"
}
},
"loggers": {
"foo": {
"handlers": ["null"],
"propagate": False
}
}
})
)由记录器的处理程序及其祖先记录器发出。
注意。—将记录器的属性logging.getLogger("foo.bar")
设置为disabled
并不是另一种方法,因为它不是公共API的一部分。参见https://bugs.python.org/issue36318:
True
答案 9 :(得分:2)
你也可以:
handlers = app.logger.handlers
# detach console handler
app.logger.handlers = []
# attach
app.logger.handlers = handlers
答案 10 :(得分:2)
我不太了解日志记录模块,但我正在以通常只想禁用调试(或信息)消息的方式使用它。您可以使用Handler.setLevel()
将日志记录级别设置为CRITICAL或更高。
此外,您可以通过打开文件来替换sys.stderr和sys.stdout。见http://docs.python.org/library/sys.html#sys.stdout。但我不建议这样做。
答案 11 :(得分:1)
通过在“ 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,
},
}
})
答案 12 :(得分:1)
这将防止来自第三个库的所有日志记录(如此处所述) https://docs.python.org/3/howto/logging.html#configuring-logging-for-a-library
logging.getLogger('somelogger').addHandler(logging.NullHandler())
答案 13 :(得分:0)
如果您要暂时禁用某个记录器,请执行以下操作。
示例日志
2019-10-02 21:28:45,663 django.request PID: 8 Internal Server Error: /service_portal/get_all_sites
代码
django_request_logger = logging.getLogger('django.request')
django_request_logger.disabled = True
django_request_logger.disabled = False
答案 14 :(得分:0)
使用装饰器找到了一种优雅的解决方案,该解决方案解决了以下问题:如果您要编写一个具有多个功能的模块,每个功能具有多个调试消息,并且您希望禁用所有功能,则该怎么办?功能,但您当前关注的是那一个?
您可以使用装饰器来做到这一点:
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
的调试消息。
这样可以确保您只看到您关注的功能中的调试消息。
希望有帮助!
答案 15 :(得分:0)
您可以更改特定处理程序的调试模式级别,而不是完全禁用它。
因此,如果您遇到某种情况,则只想停止控制台的调试模式,但仍然需要保留其他级别,例如Error。您可以按照以下步骤进行操作
# 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)
答案 16 :(得分:-1)
子类化您想要暂时禁用的处理程序:
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()