如何在Python中禁用标准错误流的日志记录?这行不通:

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.

这将防止日志被发送到包含控制台日志的上层记录器。

其他回答

完全禁用日志记录:

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)

第一个解决方案的问题是它只适用于根日志记录器。使用logging.getLogger(__name__)创建的其他记录器不会被此方法禁用。

第二个解决方案确实会影响所有日志。但是它将输出限制在给定级别之上,因此可以通过记录级别大于50的日志来覆盖它。

这可以通过

logging.disable(sys.maxint)

据我所知(在查看源代码后),这是完全禁用日志记录的唯一方法。

这将防止所有来自第三个库的日志记录,就像这里描述的那样 https://docs.python.org/3/howto/logging.html#configuring-logging-for-a-library

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

使用上下文管理器-[最简单]

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()

如果你需要[更复杂的]细粒度的解决方案,你可以看看AdvancedLogger

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

AdvancedLogger的用例

# 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"}

使用装饰器找到了一个优雅的解决方案,它解决了以下问题:如果您正在编写一个具有多个函数的模块,每个函数都有几个调试消息,并且您希望禁用除当前关注的函数之外的所有函数的登录,该怎么办?

你可以使用装饰器:

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_being_focused内部调用function_already_debug,也不会显示来自function_already_debug的调试消息。 这确保您将只看到您所关注的函数的调试消息。

希望能有所帮助!

这不是100%的解决方案,但这里没有一个答案解决了我的问题。我有自定义的日志模块,根据严重程度输出彩色文本。我需要禁用stdout输出,因为它复制了我的日志。我对将关键日志输出到控制台很满意,因为我几乎不使用它。我没有测试它是否为stderr,因为我没有在日志中使用它,但它应该与stdout的工作方式相同。它将CRITICAL设置为仅针对stdout的最小严重程度(如果请求则为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)