如何防止 Python Tornado 登录到 stdout/console?

How to prevent Python Tornado from logging to stdout/console?

我需要禁止 Tornado 记录到 STDOUT。我正在使用 Python 3.8,在 Ubuntu 18.04 上 运行。我希望我的日志语句仅由旋转文件记录器处理。问题是记录的语句被记录到文件中,也被记录到控制台:

import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger("ex_logger")

nh = logging.NullHandler()

rfh = RotatingFileHandler(filename="./logs/process.log", mode='a', maxBytes=50000000, backupCount=25, encoding=None, delay=False)
rfh.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
rfh.setFormatter(formatter)

logger.handlers = []
logger.propagete = False
logger.addHandler(rfh)

logging.getLogger("tornado.access").handlers = []
logging.getLogger("tornado.application").handlers = []
logging.getLogger("tornado.general").handlers = []

logging.getLogger("tornado.access").addHandler(nh)
logging.getLogger("tornado.application").addHandler(nh)
logging.getLogger("tornado.general").addHandler(nh)

logging.getLogger("tornado.access").propagate = False
logging.getLogger("tornado.application").propagate = False
logging.getLogger("tornado.general").propagate = False

....

def main():

    ######
    # this message eppears in both the output log file and stdout
    ######
    logger.info(" application init ... ")
    
    asyncio.set_event_loop_policy(tornado.platform.asyncio.AnyThreadEventLoopPolicy())
    tornado.options.parse_command_line()
    app = Application()
    app.listen(options.port)
    tornado.ioloop.IOLoop.current().start()


if __name__ == "__main__":
    main()

您还需要为根处理程序 (logging.getLogger("")) 定义日志记录策略。 Tornado 查看根处理程序来决定日志记录是否已经配置或需要默认设置。

问题是,从您启动 IDE 的那一刻起,logging.getLogger("tornado") 可能会附加一个 StreamHandler。这不会发生在每个 IDE 上,但它确实发生在 Spyder 上。所以这是你必须用 NullHandler:

替换的那个
import logging
nh = logging.NullHandler()
tornado_logger = logging.getLogger("tornado")
tornado_logger.handlers.clear()
# tornado_logger.handlers = []  # would work instead of .clear() but it's best practice to change the list and not replace it, just in case some other variable name somewhere else still refers to it.
tornado_logger.addHandler(nh)

您不需要对 "tornado" 记录器的子项做任何事情,例如"tornado.access",等等。