logging

logging是Python自带的日志标准库

需求:同时将日志输出到控制台及写入文件

编写工具类

utils/log.py

  1. import logging
  2. import os
  3. # 1. 创建一个logger
  4. logger = logging.getLogger('simple_example')
  5. logger.setLevel(logging.DEBUG) # Log等级总开关
  6. # 2.控制台的handler
  7. ch = logging.StreamHandler()
  8. ch.setLevel(logging.DEBUG)
  9. # 3. 写入文件的handler
  10. root_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
  11. fh = logging.FileHandler(filename=os.path.join(root_dir, 'log/run.log'), encoding='utf-8')
  12. # 4. 定义handler的输出格式
  13. format ='%(asctime)s - %(filename)s - %(lineno)d - %(name)s - %(levelname)s - %(message)s'
  14. formatter = logging.Formatter(fmt=format)
  15. ch.setFormatter(formatter)
  16. fh.setFormatter(formatter)
  17. # 将logger添加到handler里面
  18. logger.addHandler(ch)
  19. logger.addHandler(fh)

Formatter格式化有以下参数

  1. %(name)s Name of the logger (logging channel)
  2. %(levelno)s 打印日志级别的数值
  3. %(levelname)s 打印日志级别的名称
  4. %(pathname)s 打印当前执行程序的路径,其实就是 sys.argv [0]
  5. %(filename)s 打印当前执行程序名
  6. %(module)s 打印当前模块名
  7. %(lineno)d 打印日志的当前行号
  8. %(funcName)s Function name
  9. %(created)f Time when the LogRecord was created (time.time()
  10. return value)
  11. %(asctime)s Textual time when the LogRecord was created
  12. %(msecs)d Millisecond portion of the creation time
  13. %(relativeCreated)d Time in milliseconds when the LogRecord was created,
  14. relative to the time the logging module was loaded
  15. (typically at application startup time)
  16. %(thread)d Thread ID (if available)
  17. %(threadName)s Thread name (if available)
  18. %(process)d Process ID (if available)
  19. %(message)s The result of record.getMessage(), computed just as
  20. the record is emitted

使用

要在别的文件中中使用from utils.log import logger

  1. import pymysql
  2. from utils.log import logger
  3. if __name__ == '__main__':
  4. try:
  5. # 创建连接对象
  6. db = pymysql.connect(host='localhost',
  7. user='root',
  8. passwd='',
  9. db='ehsy', # 数据库名字
  10. port=3306,
  11. autocommit=True, # 指定 autocommit 为 True
  12. charset='utf8')
  13. # 创建游标对象
  14. # pymysql.cursors.DictCursor 以字典的形式返回查询出来的数据
  15. cursor = db.cursor(pymysql.cursors.DictCursor)
  16. except Exception as e:
  17. logger.error('数据库连接失败{}'.format(e))

控制台输出:
image.png
日志文件写入:

  1. 2022-05-24 14:18:58,825 - logging_use2.py - 18 - simple_example - ERROR - 数据库连接失败(2003, "Can't connect to MySQL server on 'localhost' ([WinError 10061] 由于目标计算机积极拒绝,无法连接。)")

Loguru

Loguru是一个旨在为Python带来愉快日志记录的第三方库。更加优雅、高效、简洁的

安装

Loguru 仅支持 Python 3.5 及以上的版本,使用 pip 安装即可:

  1. pip install loguru

简单使用

  1. from loguru import logger
  2. logger.info("This is log info!")
  3. logger.warning("This is log warn!")
  4. logger.error("This is log error!")
  5. logger.debug("This is log debug!")

控制台输出:
image.png

add()函数

与 logging 模块不同,要想自定义日志级别以及格式,不需要 Handler,不需要 Formatter,只需要一个 add() 函数就可以, add() 语句的详细参数:

  1. def add(
  2. self,
  3. sink,
  4. *,
  5. level=_defaults.LOGURU_LEVEL,
  6. format=_defaults.LOGURU_FORMAT,
  7. filter=_defaults.LOGURU_FILTER,
  8. colorize=_defaults.LOGURU_COLORIZE,
  9. serialize=_defaults.LOGURU_SERIALIZE,
  10. backtrace=_defaults.LOGURU_BACKTRACE,
  11. diagnose=_defaults.LOGURU_DIAGNOSE,
  12. enqueue=_defaults.LOGURU_ENQUEUE,
  13. catch=_defaults.LOGURU_CATCH,
  14. **kwargs
  15. ):

参数讲解:
https://loguru.readthedocs.io/en/stable/api/logger.html
https://segmentfault.com/a/1190000040911280

将日志输出到文件

  1. from loguru import logger
  2. import os
  3. root_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
  4. filename =os.path.join(root_dir, 'log/run.log')
  5. logger.add(filename)
  6. logger.info('this is a info')

rotation 日志文件分隔

设置超过 500 MB 新创建一个 log 文件:

  1. from loguru import logger
  2. logger.add('run_{time}.log', rotation="500 MB")
  3. logger.info('this is a info')

通过这样的配置我们就可以实现每 500MB 存储一个文件,每个 log 文件过大就会新创建一个 log 文件。我们在配置 log 名字时加上了一个 time 占位符,这样在生成时可以自动将时间替换进去,生成一个文件名包含时间的 log 文件。

设置每隔一个周新创建一个 log 文件:

  1. logger.add('runtime_{time}.log', rotation='1 week')

retention 配置

很多情况下,一些非常久远的 log 对我们来说并没有什么用处了,它白白占据了一些存储空间,不清除掉就会非常浪费。retention 这个参数可以配置日志的最长保留时间。
比如我们想要设置日志文件最长保留 10 天,可以这么来配置:

  1. logger.add('run.log', retention='10 days')
  2. #可以传入 Examples: "1 week, 3 days", "2 months"

设置日志文件最多保留 10 个:

  1. logger.add('runtime_{time}.log', retention=10)

也可以是一个 datetime.timedelta 对象,比如设置日志文件最多保留 5 个小时:

  1. import datetime
  2. from loguru import logger
  3. logger.add('runtime_{time}.log', retention=datetime.timedelta(hours=5))

compression 日志压缩格式

add() 函数的 compression 参数,可以配置日志文件的压缩格式,这样可以更加节省存储空间,比如设置使用 zip 文件格式保存:

  1. logger.add('runtime_{time}.log', compression='zip')

其格式支持:gz、bz2、xz、lzma、tar、tar.gz、tar.bz2、tar.xz


封装成工具类

如果我们要在多个模块中都使用loguru,将日志写入,我们需要多次设置logger.add( ),没办法一次性设置后,多次使用,这是我们可以封装成工具类
utils/Loggings.py

  1. import os
  2. from loguru import logger
  3. class Loggings:
  4. root_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
  5. filename = os.path.join(root_dir, 'log/run.log')
  6. __instance = None
  7. logger.add(
  8. sink=filename, # 写入文件路径
  9. rotation="500MB",
  10. encoding="utf-8",
  11. enqueue=True,
  12. retention="10 days"
  13. )
  14. def __new__(cls, *args, **kwargs):
  15. if not cls.__instance:
  16. cls.__instance = super(Loggings, cls).__new__(cls, *args, **kwargs)
  17. return cls.__instance
  18. def info(self, msg):
  19. return logger.info(msg)
  20. def debug(self, msg):
  21. return logger.debug(msg)
  22. def warning(self, msg):
  23. return logger.warning(msg)
  24. def error(self, msg):
  25. return logger.error(msg)

调用:

  1. from utils.Loggings import Loggings
  2. log = Loggings()
  3. log.info('this is a info')