Python logging 日志配置,如何不输出到控制台

我的日志配置如下,运行时自动输出到控制台,用 nohup 挂起,相应的输出也会输出 nohup.out 同时 my.log 也会有正确的日志输出 my.log 的日志输出格式是正确的,输出到控制台的日志和 ide ( pychram )调试时产生的日志一样

logHandler = TimedRotatingFileHandler("logs/my.log", when="midnight")
logFormatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
logHandler.setFormatter(logFormatter)
logger = logging.getLogger('myapp')
logger.addHandler(logHandler)
logger.setLevel(logging.INFO)

具体应该怎么修改才能保证日志不输出两次?大佬们指导下


Python logging 日志配置,如何不输出到控制台

8 回复

你添加一个 StreamHandler,然后把他的 level 设置为 Fatal,这样就不会自动输出了。


import logging

# 方案1:移除默认的StreamHandler(推荐)
def setup_logging_no_console():
    # 创建logger
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    
    # 移除所有现有的handler
    for handler in logger.handlers[:]:
        logger.removeHandler(handler)
    
    # 只添加FileHandler,不添加StreamHandler
    file_handler = logging.FileHandler('app.log', encoding='utf-8')
    file_handler.setLevel(logging.DEBUG)
    
    # 设置格式
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    file_handler.setFormatter(formatter)
    
    logger.addHandler(file_handler)
    return logger

# 方案2:创建新的logger实例(更干净)
def create_new_logger():
    logger = logging.getLogger('my_app')
    logger.setLevel(logging.DEBUG)
    logger.propagate = False  # 防止传播到root logger
    
    # 只添加文件处理器
    fh = logging.FileHandler('my_app.log')
    fh.setLevel(logging.DEBUG)
    
    formatter = logging.Formatter(
        '%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s'
    )
    fh.setFormatter(formatter)
    
    logger.addHandler(fh)
    return logger

# 方案3:配置logging字典(Python 3.2+)
import logging.config

LOGGING_CONFIG = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'class': 'logging.FileHandler',
            'filename': 'app.log',
            'formatter': 'detailed',
            'encoding': 'utf-8'
        }
    },
    'formatters': {
        'detailed': {
            'format': '%(asctime)s %(levelname)s %(message)s'
        }
    },
    'root': {
        'level': 'INFO',
        'handlers': ['file']  # 只包含文件handler,没有控制台
    }
}

# 使用示例
if __name__ == '__main__':
    # 方法1使用
    logger1 = setup_logging_no_console()
    logger1.info("这条日志只会写入文件,不会输出到控制台")
    
    # 方法2使用
    logger2 = create_new_logger()
    logger2.debug("Debug信息只到文件")
    logger2.error("错误信息也只到文件")
    
    # 方法3使用
    logging.config.dictConfig(LOGGING_CONFIG)
    logging.info("通过dictConfig配置的日志")

关键就一点:别给logger加StreamHandler就行。用FileHandler写文件,或者用NullHandler啥都不输出。

nohup 把输出流定向到 null 设备,这样就只有你 log 文件的那部分日志输出
参考资料: http://linux.vbird.org/linux_basic/0320bash.php#redirect_redirect


找到个
<br>logger.propagate = False<br>
这样就不会输出到控制台,也不会输出到 nohup.out

大佬这个也是个解决方法

logger 是有继承关系的,子 logger 会把日志向上传给父 logger 的 handlers 处理。
你的 ‘myapp’ logger 上面还有个 root logger (logging.getLogger(name=None)),因为在某个地方设置了 root logger 输出到控制台,所以 ‘myapp’ logger 的日志也会输出到控制台。
logger.propagate = False 是让子 logger 不把日志向上传给父 logger。但是如果 root logger 还有其它子 logger (例如其它第三方库的 logger ),它们的日志仍会输出到控制台。
更为根本的解决方法是设置 root logger 不再输出到控制台(移除 StreamHandler )。

logging.basicConfig()试试

logging.basicConfig(
format=’%(asctime)s : %(levelname)s : %(message)s’,
level=logging.INFO,
filename=’/dev/null’,
filemode=‘w’)

读下相关源码也就个把小时

回到顶部