python中的log日志多线程安全

 更新时间:2023年08月15日 08:38:15   作者:peach_orange  
这篇文章主要介绍了python中的log日志多线程安全,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

python log日志多线程安全

python中的日志文件为logger,常用的有两个-RotatingFileHandler;TimedRotatingFileHandler。

文件没满足分割条件前,保存在‘info.log’(自己命名的文件)中,如果满足分割条件,会生成‘info.log.1’。

下一次满足分割条件后,将‘info.log’保存成‘info.log.1’,而‘info.log.1’顺延成‘info.log.2’;满足最多保存的个数后,会将其删掉。

RotatingFileHandler,是按大小划分日志文件,使用方法如下。

RotatingFileHandler是按文件大小自动分割保存,下文中设置的是1M保存一个文件,最多保存30个。

此种方式支持多线程安全,支持软件的开关机(TimedRotatingFileHandler不支持,一旦关机,会重新计时)

import logging
from logging import handlers
def log_init():
    log = logging.getLogger('error.log')            # log保存位置
    format_str = log.Formatter('%(asctime)s - \     # log时间戳格式
        %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')                         
    log.setLevel(logging.DEBUG)                     # log日志等级(往下的内容不保存)
    sh = logging.StreamHandler()                    # 往屏幕上输出
    # filename:log文件名;maxBytes:超过最大尺寸,log会另存一个文件;
    # backupCount:最多保存多少个日志;encoding:保存编码格式
    th = handlers.RotatingFileHandler(filename='error.log', maxBytes=1024*1024, \
                                    backupCount=30, encoding='uft-8')        
    th.setFormatter(format_str)                     # 设置文件里写入的格式
    log.addHandler(sh)
    log.addHandler(th)
    return log
if __name__ == '__main__':
    log = log_init()
    log.debug('debug_msg')
    log.info('info_msg')
    log.warning('warning_msg')
    log.error('error_msg')
    log.critical('critical_msg')

TimedRotatingFileHandler是按日期划分日志文件,使用方法如下。

TimedRotatingFileHandler是按文件大小自动分割保存,下文中设置的是每天保存一个log文件,最多保存30个。

此种方式支持多线程不安全,不支持软件的关机(软件关机后,会重新计时,如果经常关机的项目,会只记录在一个文件中)。

import logging
from logging import handlers
def log_init():
    log = logging.getLogger('error.log')            # log保存位置
    format_str = log.Formatter('%(asctime)s - \     # log时间戳格式
        %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')                         
    log.setLevel(logging.DEBUG)                     # log日志等级(往下的内容不保存)
    sh = logging.StreamHandler()                    # 往屏幕上输出
    # filename:log文件名;when:多久另存一个文件(S/M/H/D/W/midnight);
    # backupCount:最多保存多少个日志;encoding:保存编码格式
    th = handlers.TimedRotatingFileHandler(filename='error.log', when='D', \
                                    backupCount=30, encoding='uft-8')        
    th.setFormatter(format_str)                     # 设置文件里写入的格式
    log.addHandler(sh)
    log.addHandler(th)
    return log
if __name__ == '__main__':
    log = log_init()
    log.debug('debug_msg')
    log.info('info_msg')
    log.warning('warning_msg')
    log.error('error_msg')
    log.critical('critical_msg')

如果想多线程使用TimedRotatingFileHandler,就需要自己写一个线程,然后每一个log往消息队列中丢,用线程处理这个消息队列。

Queue是线程安全的,所以作为消息队列使用没有影响。

import time
import _thread
import logging
from logging import handlers
from queue import Queue
logs_queue = Queue()
class LogMsg(object):
    def __init__(self, type, msg):
        self._type = type
        self._msg = msg
def log_init():
    log = logging.getLogger('error.log')            # log保存位置
    format_str = log.Formatter('%(asctime)s - \     # log时间戳格式
        %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')                         
    log.setLevel(logging.DEBUG)                     # log日志等级(往下的内容不保存)
    sh = logging.StreamHandler()                    # 往屏幕上输出
    # filename:log文件名;when:多久另存一个文件(S/M/H/D/W/midnight);
    # backupCount:最多保存多少个日志;encoding:保存编码格式
    th = handlers.TimedRotatingFileHandler(filename='error.log', when='D', \
                                    backupCount=30, encoding='uft-8')        
    th.setFormatter(format_str)                     # 设置文件里写入的格式
    log.addHandler(sh)
    log.addHandler(th)
    return log
def cop_log_queue(logger):
    while True:
        if logs_queue.empty():
           time.sleep(1)
        log_msg = logs_queue.get()
        if log_msg._type == 'debug':
            logger.debug(log_msg._msg)
        elif log_msg._type == 'info':
            logger.info(log_msg._msg)
        elif log_msg._type == 'warning':
            logger.warning(log_msg._msg)
        elif log_msg._type == 'error':
            logger.error(log_msg._msg)
        elif log_msg._type == 'critical':
            logger.critical(log_msg._msg)
def error_thread1():
    while True:
        logs_queue.put(LogMsg('debug','debug_msg'))
        time.sleep(1)
def error_thread2():
    while True:
        logs_queue.put(LogMsg('info','info_msg'))
        time.sleep(1)
if __name__ == '__main__':
    logger = log_init()
    _thread.start_new_thread(cope_log_queue, (logger, ))
    _thread.start_new_thread(error_thread1, ())
    _thread.start_new_thread(error_thread2, ())

python之log日志

记录程序日志信息的目的是

  • 可以很方便的了解程序的运行情况
  • 可以分析用户的操作行为、喜好等信息
  • 方便开发人员检查bug

logging日志级别介绍

日志等级可以分为5个,从低到高分别是:

  • DEBUG
  • INFO
  • WARNING
  • ERROR
  • CRITICAL

日志等级说明:

  • DEBUG:程序调试bug时使用
  • INFO:程序正常运行时使用
  • WARNING:程序未按预期运行时使用,但并不是错误,如:用户登录密码错误
  • ERROR:程序出错误时使用,如:IO操作失败
  • CRITICAL:特别严重的问题,导致程序不能再继续运行时使用,如:磁盘空间为空,一般很少使用
  • 默认的是WARNING等级,当在WARNING或WARNING之上等级的才记录日志信息。
  • 日志等级从低到高的顺序是: DEBUG < INFO < WARNING < ERROR < CRITICAL

logging日志的使用

在 logging 包中记录日志的方式有两种:

  • 输出到控制台
  • 保存到日志文件

日志信息输出到控制台的示例代码:

import logging
logging.debug('这是一个debug级别的日志信息')
logging.info('这是一个info级别的日志信息')
logging.warning('这是一个warning级别的日志信息')
logging.error('这是一个error级别的日志信息')
logging.critical('这是一个critical级别的日志信息')

运行结果:

WARNING:root:这是一个warning级别的日志信息
ERROR:root:这是一个error级别的日志信息
CRITICAL:root:这是一个critical级别的日志信息

说明:

日志信息只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING

logging日志等级和输出格式的设置:

import logging
# 设置日志等级和输出日志格式
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
logging.debug('这是一个debug级别的日志信息')
logging.info('这是一个info级别的日志信息')
logging.warning('这是一个warning级别的日志信息')
logging.error('这是一个error级别的日志信息')
logging.critical('这是一个critical级别的日志信息')

运行结果:

2019-02-13 20:41:33,080 - hello.py[line:6] - DEBUG: 这是一个debug级别的日志信息
2019-02-13 20:41:33,080 - hello.py[line:7] - INFO: 这是一个info级别的日志信息
2019-02-13 20:41:33,080 - hello.py[line:8] - WARNING: 这是一个warning级别的日志信息
2019-02-13 20:41:33,080 - hello.py[line:9] - ERROR: 这是一个error级别的日志信息
2019-02-13 20:41:33,080 - hello.py[line:10] - CRITICAL: 这是一个critical级别的日志信息

代码说明:

  • level 表示设置的日志等级
  • format 表示日志的输出格式, 参数说明:
  • %(levelname)s: 打印日志级别名称
  • %(filename)s: 打印当前执行程序名
  • %(lineno)d: 打印日志的当前行号
  • %(asctime)s: 打印日志的时间
  • %(message)s: 打印日志信息

日志信息保存到日志文件的示例代码:

import logging
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                    filename="log.txt",
                    filemode="w")
logging.debug('这是一个debug级别的日志信息')
logging.info('这是一个info级别的日志信息')
logging.warning('这是一个warning级别的日志信息')
logging.error('这是一个error级别的日志信息')
logging.critical('这是一个critical级别的日志信息')

 会在此目录中自动生成log.txt文件,生成日志数据

运行结果:

2022-01-15 11:31:14,529 - web.py[line:59] - INFO: 动态资源请求:/index.html
2022-01-15 11:31:22,542 - web.py[line:63] - INFO: 静态资源请求:/df
2022-01-15 11:46:14,034 - web.py[line:60] - INFO: 动态资源请求:/index.html
2022-01-15 11:46:14,036 - web.py[line:60] - INFO: 动态资源请求:/index.html
2022-01-15 11:47:24,065 - web.py[line:60] - INFO: 动态资源请求:/index.html
2022-01-15 11:47:26,655 - web.py[line:60] - INFO: 动态资源请求:/index.html
2022-01-15 11:47:45,224 - web.py[line:75] - INFO: 静态资源请求:/favicon.ico
2022-01-15 11:52:15,723 - web.py[line:60] - INFO: 动态资源请求:/index.html
2022-01-15 11:52:23,513 - web.py[line:60] - INFO: 动态资源请求:/index.html
2022-01-15 11:52:31,315 - web.py[line:60] - INFO: 动态资源请求:/index.html
2022-01-15 11:52:36,838 - web.py[line:75] - INFO: 静态资源请求:/favicon.ico

logging日志在mini-web项目中应用

web.py 程序使用logging日志示例:

1.程序入口模块设置logging日志的设置

 import socket
 import threading
 import sys
 import framework
 import logging
 # logging日志的配置
 logging.basicConfig(level=logging.DEBUG,
                     format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                     filename="log.txt",
                     filemode="w")

2.INFO级别的日志输出,示例代码:

 # 判断是否是动态资源请求
 if request_path.endswith(".html"):
     """这里是动态资源请求,把请求信息交给框架处理"""
     logging.info("动态资源请求:" + request_path)
     ...
 else:
     """这里是静态资源请求"""
     logging.info("静态资源请求:" + request_path)
     ...

3.WARNING级别的日志输出,示例代码:

 # 获取命令行参数判断长度
 if len(sys.argv) != 2:
     print("执行命令如下: python3 xxx.py 9000")
     logging.warning("用户在命令行启动程序参数个数不正确!")
     return
 # 判断端口号是否是数字
 if not sys.argv[1].isdigit():
     print("执行命令如下: python3 xxx.py 9000")
     logging.warning("用户在命令行启动程序参数不是数字字符串!")
     return

framework.py 程序使用logging日志示例:

ERROR级别的日志输出,示例代码:

 # 处理动态资源请求
 def handle_request(env):
     # 获取动态请求资源路径
     request_path = env["request_path"]
     print("接收到的动态资源请求:", request_path)
     # 遍历路由列表,选择执行的函数
     for path, func in route_list:
         if request_path == path:
             result = func()
             return result
     else:
         logging.error("没有设置相应的路由:" + request_path)
         # 没有找到动态资源
         result = not_found()
         return result

说明:

  • logging日志配置信息在程序入口模块设置一次,整个程序都可以生效。
  • logging.basicConfig 表示 logging 日志配置操作

小结

记录python程序中日志信息使用 logging 包来完成

logging日志等级有5个:

  • DEBUG
  • INFO
  • WARNING
  • ERROR
  • CRITICAL

打印(记录)日志的函数有5个:

  • logging.debug函数, 表示: 打印(记录)DEBUG级别的日志信息
  • logging.info函数, 表示: 打印(记录)INFO级别的日志信息
  • logging.warning函数, 表示: 打印(记录)WARNING级别的日志信息
  • logging.error函数, 表示: 打印(记录)ERROR级别的日志信息
  • logging.critical函数, 表示: 打印(记录)CRITICAL级别的日志信息

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Python 脚本实现淘宝准点秒杀功能

    Python 脚本实现淘宝准点秒杀功能

    这篇文章主要介绍了python实现淘宝准点秒杀脚本,本文图文实例相结合给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-11-11
  • python实现百度关键词排名查询

    python实现百度关键词排名查询

    这篇文章主要介绍了python实现百度关键词排名查询,需要的朋友可以参考下
    2014-03-03
  • python三引号如何输入

    python三引号如何输入

    在本篇文章里小编给大家整理的是关于python三引号输入方法及相关实例,需要的朋友们可以学习下。
    2020-07-07
  • python 使用多线程创建一个Buffer缓存器的实现思路

    python 使用多线程创建一个Buffer缓存器的实现思路

    这篇文章主要介绍了python 使用多线程创建一个Buffer缓存器的实现思路,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • python 抓取知乎指定回答下视频的方法

    python 抓取知乎指定回答下视频的方法

    这篇文章主要介绍了python 抓取知乎指定回答下视频的方法,文中讲解非常详细,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • python算法测试结果自动保存到excel表格的实现步骤

    python算法测试结果自动保存到excel表格的实现步骤

    我们在进行算法评估是通常会针对每个样本的算法处理结果进行统计,例如每个样本正确预测数量、漏检数量和误检数量、精度等,本文小编将给大家介绍python算法测试结果自动保存到excel表格的实现步骤,感兴趣的朋友可以参考下
    2023-12-12
  • Python递归函数返回值为None问题及解决

    Python递归函数返回值为None问题及解决

    文章主要讨论了在Python中使用递归函数时可能出现的问题,特别是递归函数的返回值不符合预期的情况,文章通过一个具体的例子说明了这个问题,并解释了如何通过在递归调用时加上return语句来解决这个问题
    2024-11-11
  • python导出requirements.txt的几种方法以及环境配置详细流程

    python导出requirements.txt的几种方法以及环境配置详细流程

    这篇文章主要给大家介绍了关于python导出requirements.txt的几种方法以及环境配置详细流程,requirements.txt 文件是一个文本文件,用于列出你的Python项目所依赖的软件包及其版本,需要的朋友可以参考下
    2023-11-11
  • python如何编写win程序

    python如何编写win程序

    在本篇文章里小编给大家分享的是关于python编写win程序的实例内容,有需要的朋友们可以学习下。
    2020-06-06
  • python判断列表字典字符串元组是否存在某个值或者空值(多种方法)

    python判断列表字典字符串元组是否存在某个值或者空值(多种方法)

    这篇文章主要介绍了python判断列表字典字符串元组是否存在某个值或者空值,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-02-02

最新评论