python 在多个模块中记录日志


一、

无论对 logging.getLogger('someLogger') 进行多少次调用,都会返回同一个 logger 对象的引用。不仅在同一个模块内如此,只要是在同一个 Python 解释器进程中,跨模块调用也是一样。同样是引用同一个对象,应用程序也可以在一个模块中定义和配置一个父 logger,而在另一个单独的模块中创建(但不配置)子 logger,对于子 logger 的所有调用都会传给父 logger。

参考链接:https://docs.python.org/zh-cn/3/howto/logging-cookbook.html

二、

问题:python 中封装日志 logging,为何打印行号固定在同一行?

答:打印的行号是调用 logger 对象的所在行,所以自己进行封装时,应该返回 logger 对象,再调用相应logger.info、logger.debug等方法。

参考链接:https://testerhome.com/topics/26827

三、代码示例:

#!/usr/bin/env python
# coding:utf-8

import logging,time
import os

def get_logger(log_path):
    # log_path是存放日志的路径,如果不存在这个logs文件夹,那么需要创建出来。
    # 文件的命名
    logname = os.path.join(log_path, '%s.log'%time.strftime('%Y_%m_%d'))
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    # 日志输出格式
    formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
    # 创建一个FileHandler,存储日志文件
    fh = logging.FileHandler(logname, encoding='utf-8')
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(formatter)
    logger.addHandler(fh)
    # 创建一个StreamHandler,用于输出到控制台
    sh = logging.StreamHandler()
    sh.setLevel(logging.DEBUG)
    sh.setFormatter(formatter)
    logger.addHandler(sh)
    return logger

if __name__ == '__main__':
    # log_path是存放日志的路径
    cur_path = os.path.dirname(os.path.realpath(__file__))
    log_path = os.path.join(os.path.dirname(cur_path), '../log')
    # 如果不存在这个logs文件夹,就自动创建一个
    if not os.path.exists(log_path): os.mkdir(log_path)
    log = get_logger(log_path)
    log.info(u'基础信息')
    log.debug(u'调试信息')
    log.warning(u'警告信息')
    log.error(u'错误信息')

测试代码bconfig.py

#!/usr/bin/env python
# coding:utf-8


if __name__ == "__main__":
    from log import get_logger
    log_path = '/root/AutotestV2/log'
    log = get_logger(log_path)
    log.info("run test")

运行测试代码bconfig.py结果如下:

可以看到打印出了log.info("run test")所在文件和行号。

[root@localhost utils]# python bconfig.py 
2022-01-25 18:54:42,386 bconfig.py[line:9] INFO run test