您的位置:首页 > 编程语言 > Python开发

初识 python logging 模块,希望能帮助正在或准备学习该模块的朋友

2018-12-19 23:08 337 查看

logging 模块使用

logging 用法解析

  1. 初始化:
import logging
# 初始化
logger = logging.getLogger("test")
# 返回一个logger实例,如果没有指定name,返回root logger。
#只要name相同,返回的logger实例都是同一个而且只有一个,即name和logger实例是一一对应的。
# 这意味着,无需把logger实例在各个模块中传递。只要知道name,就能得到同一个logger实例。

getLogger() 方法后面最好加上所要日志记录的模块名字,在formatter日志格式中的%(name)s 对应的是这里的模块名.
2. 设置级别:
# 设置日志级别
logger.setLevel(level=“DEBUG”)
Logging中有NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL这几种级别,日志会记录设置级别以上的日志.
3. 实例化 Handler
常用的是 StreamHandler 和 FileHandler 一个将日志打印在CMD窗口上, 一个将日志记录在文件上

  • 建立一个filehandler 将日志输出在指定文件中
fh = logging.FileHandler(LOG_FILE, maxBytes=1024 * 1024, backupCount=5,
encoding='utf-8'") # 添加encoding 解决输出文件乱码问题
fh.setLevel(logging.DEBUG)
  • 建立一个streamhandler将日志打印在CMD窗口上
sh = logging.StreamHandler()
sh.setLevel(logging.ERROR)
  1. 设置格式:
    formatter 定义了最终log信息的顺序和内容
    %(name)s Logger的名字
    %(levelname)s 文本形式的日志级别
    %(message)s 用户输出的消息
    %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    %(levelno)s 数字形式的日志级别
    %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
    %(filename)s 调用日志输出函数的模块的文件名
    %(module)s 调用日志输出函数的模块名
    %(funcName)s 调用日志输出函数的函数名
    %(lineno)d 调用日志输出函数的语句所在的代码行
    %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
    %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
    %(thread)d 线程ID。可能没有
    %(threadName)s 线程名。可能没有
    %(process)d 进程ID。可能没有
    格式可根据需求或使用习惯自行组合
    以下代码中为本人习惯的格式
    formatter = logging.Formatter(“%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s”)
    sh.setFormatter(formatter)
    fh.setFormatter(formatter)
  2. 将 Handler 添加到 logger 对象中
    logger.addHandler(sh)
    logger.addHandler(fh)
    通过handler对象可以把日志内容写到不同的地方。比如StreamHandler就是把日志写到控制台。python提供了十几种实用handler,比较常用有:
    1 StreamHandler: 输出到控制台
    2 FileHandler: 输出到文件
    3 BaseRotatingHandler 可以按时间写入到不同的日志中。比如将日志按天写入不同的日期结尾的文件文件。
    4 SocketHandler 用TCP网络连接写LOG
    5 DatagramHandler 用UDP网络连接写LOG
    6 SMTPHandler 把LOG写成EMAIL邮寄出去

    封装

    工作中需要经常使用logging模块,可以将以上代码封装成类在进行实例化调用,以下代码是我初步了解logging模块后根据自己工作需要封装的log模块
    import logging
    import os
    
    class Logger(object):
    def __init__(self, log_level="DEBUG", sh_log_level=None, fh_log_level=None, write_mode="w", log_path=None):
    """
    实例化一个logger对象,根据传入参数以不同方式输出日志
    1,使用默认参数,仅在控制台输出DEBUG登记信息
    2.给sh_log_level传入日志等级,在控制台输出加入格式后的日志信息
    3.给fh_log_level传入日志等级,在文件中输出加入格式后的日志信息
    
    :param log_level:初始化日志等级
    :param log_path:输出日志文件路径,若无指定路径则将log文件夹生成在入口文件目录中.
    :param fh_log_level:控制台输出日志等级
    :param sh_log_level:文件输出日志等级
    :param write_mode:日志写入方式 "w"覆盖 "a"追加
    """
    # 创建一个logger
    self.logger = logging.getLogger()
    self.logger.setLevel(log_level)
    self.write_mode = write_mode
    level_list = ['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'NOTSET', ]
    # 定义handler的输出格式
    self.formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
    # 创建一个filehandler,用于写入日志文件
    if fh_log_level in level_list:
    if log_path is None:
    log_path = os.path.join(os.getcwd(), "log")
    os.makedirs(log_path, exist_ok=True)
    log_name = os.path.join(log_path, "running.log")
    fh = logging.FileHandler(log_name, mode=self.write_mode, encoding="utf-8")
    fh.setLevel(fh_log_level)
    fh.setFormatter(self.formatter)
    self.logger.addHandler(fh)
    # 再创建一个streamhandler,用于输出到控制台
    if sh_log_level in level_list:
    sh = logging.StreamHandler()
    sh.setLevel(sh_log_level)
    sh.setFormatter(self.formatter)
    self.logger.addHandler(sh)

`

注意:代码21行处实例化logger时最好将 level 设成 “DEBUG” 或 “NOTSET”, 若设置等级过高,后面33行,39行setlevel 时,如果设置的级别低于21行的 level ,则无法获取低于21行 level 的日志信息使用

在主函数中实例化Logger对象,传入对应的参数.

# –*– coding: utf-8 –*–
# @Time      : 2018/12/19 21:47
# @Author    : Damon_duan
# @FileName  : main.py

from log_class import Logger
import logging
# 实例化
logger = Logger("DEBUG", sh_log_level="INFO", fh_log_level="DEBUG", write_mode="a")

logging.debug("0000000000")
logging.info("1111111111111")
logging.warning("2222222222222")
logging.error("3333333333")

运行结果:
控制台显示

2018-12-19 22:42:22,464 - main.py[line:12] - INFO: 1111111111111
2018-12-19 22:42:22,464 - main.py[line:13] - WARNING: 2222222222222
2018-12-19 22:42:22,464 - main.py[line:14] - ERROR: 3333333333

文件中内容:

2018-12-19 22:39:58,810 - main.py[line:11] - DEBUG: 0000000000
2018-12-19 22:39:58,810 - main.py[line:12] - INFO: 1111111111111
2018-12-19 22:39:58,810 - main.py[line:13] - WARNING: 2222222222222
2018-12-19 22:39:58,810 - main.py[line:14] - ERROR: 3333333333

多模块共同使用

logging模块保证在同一个python解释器内,多次调用logging.getLogger(‘log_name’)都会返回同一个logger实例,即使是在多个模块的情况下。所以典型的多模块场景下使用logging的方式是在main模块中配置logging,这个配置会作用于多个的子模块,然后在其他模块中直接通过getLogger获取Logger对象即可。
如使用上面代码在main中实例了logger,只需在其他模块中 import logging随后在模块中就可以使用 logging.level 进行调用
代码及运行结果如下:
test01.py

# –*– coding: utf-8 –*–
# @Time      : 2018/12/19 22:51
# @Author    : Damon_duan
# @FileName  : test01.py
import logging

def test():
logging.info("子模块test中log信息")

main.py

# –*– coding: utf-8 –*–
# @Time      : 2018/12/19 21:47
# @Author    : Damon_duan
# @FileName  : main.py

from log_class import Logger
import logging
import test01
# 实例化
logger = Logger("DEBUG", sh_log_level="INFO", fh_log_level="DEBUG", write_mode="a")

logging.debug("0000000000")
logging.info("1111111111111")
test01.test()
logging.warning("2222222222222")
logging.error("3333333333")

运行结果:

2018-12-19 22:54:27,847 - main.py[line:13] - INFO: 1111111111111
2018-12-19 22:54:27,848 - test01.py[line:9] - INFO: 子模块test中log信息
2018-12-19 22:54:27,848 - main.py[line:15] - WARNING: 2222222222222
2018-12-19 22:54:27,848 - main.py[line:16] - ERROR: 3333333333

关于 logging 模块总结先到此,随着后续深入学习和工作中实际使用,会继续丰富本篇内容,因能力有限如本文中出现理解或书写错误,请不吝指出.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: