python全栈开发-logging模块(日记专用)

一、概述

  很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug()info()warning()error() and critical() 5个级别,其中他们级别大小关系

debug() <info() <warning() <error() <critical()  级别越低打印的日记等级就越多

下面我们看一下他是怎样的用法。

二、了解用法

1、最简单的用法

import logging

logging.debug("logging debug")
logging.info("logging info")
logging.warning("user [qianduoduo] attempted wrong password more than 3 times")
logging.error("logging error")
logging.critical("logging critical")

#输出
WARNING:root:user [qianduoduo] attempted wrong password more than 3 times
ERROR:root:logging error
CRITICAL:root:logging critical  #root  就是默认的用户名 

重点:为什么上面debug和info没有输出,那是因为一个模块默认的日志级别是warning,比他级别低的就不会输出

2、日志级别

看一下这几个日志级别分别代表什么意思,如表:

Level When it’s used
DEBUG 详细的信息,通常只有在诊断问题时才感兴趣。
INFO 确认事情按预期工作。
WARNING 表明发生了意外的事情,或预示在不久的将来会出现一些问题(例如“磁盘空间低”)。该软件仍按预期运行。
ERROR 由于一个更严重的问题,软件无法执行某些功能。
CRITICAL 一个严重的错误,表明程序本身可能无法继续运行。

3、将日记写入文件

import logging

logging.basicConfig(filename=‘duoduo.log‘,level=logging.INFO)
logging.debug(‘This message should go to the log file‘)
logging.info(‘So should this‘) logging.warning(‘And this, too‘)
logging.warning(‘And this, too‘)

#‘duoduo.log’文件输出
INFO:root:So should this
WARNING:root:And this, too   #这日记的级别设置在info,所以比他更低的debug不显示

重点: 如果我们想显示所有级别的日记就要把日记的等级设置为debug,就在level=logging.DEBUG,设置是级别的名称要大写

4、加入日期格式

  感觉上面的日志格式忘记加上时间啦,日志不知道时间怎么行呢,下面就来加上

import logging

logging.basicConfig(filename=‘duoduo.log‘,
                    level=logging.DEBUG,
                    format=‘%(asctime)s %(message)s‘,#asctime字符串形式的当前时间,message用户输出的消息
                    datefmt=‘%Y-%m-%d %I:%M:%S %p ‘)
logging.debug("logging debug")
logging.info("logging info")
logging.warning("user [qianduoduo] attempted wrong password more than 3 times")
logging.error("logging error")
logging.critical("logging critical")

#输出到文件‘duoduo.log’
2018-01-27 07:33:30 PM  logging debug
2018-01-27 07:33:30 PM  logging info
2018-01-27 07:33:30 PM  user [qianduoduo] attempted wrong password more than 3 times
2018-01-27 07:33:30 PM  logging error
2018-01-27 07:33:30 PM  logging critical

5、 format的日志格式


Logger的名字


%(levelno)s


数字形式的日志级别


%(levelname)s


文本形式的日志级别


%(pathname)s


调用日志输出函数的模块的完整路径名,可能没有


%(filename)s


调用日志输出函数的模块的文件名


%(module)s


调用日志输出函数的模块名


%(funcName)s


调用日志输出函数的函数名


%(lineno)d


调用日志输出函数的语句所在的代码行


%(created)f


当前时间,用UNIX标准的表示时间的浮 点数表示


%(relativeCreated)d


输出日志信息时的,自Logger创建以 来的毫秒数


%(asctime)s


字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒


%(thread)d


线程ID。可能没有


%(threadName)s


线程名。可能没有


%(process)d


进程ID。可能没有


%(message)s


用户输出的消息

三、log的用法,大约了解这个操作步骤

如果想同时把log打印在屏幕和文件日志里,就需要了解一点复杂的知识 了

Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适:

1、logger提供了应用程序可以直接使用的接口;

2、handler将(logger创建的)日志记录发送到合适的目的输出;

3、filter提供了细度设备来决定输出哪条日志记录;

4、formatter决定日志记录的最终输出格式。

1)、logger

①每个程序在输出信息之前都需要获得一个logger。logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的logger:


1

logger = logging.getLogger("chat.gui")

核心模块可以这样写:(自己想叫什么名称就叫什么名称)


1

logger = logging.getLogger("chat.kernel")

②logger.setLevel(lel)

说明:指定最低的日志级别,低于lel的级别将被忽略(debug是最低的内置级别,critical为最高)


1

logger.setLevel(logging.DEBUG)  #设置级别为debug级别

③Logger.addFilter(filt)、Logger.removeFilter(filt)

说明:添加或删除指定的filter

④logger.addHandler(hdlr)、logger.removeHandler(hdlr)

说明:增加或删除指定的handler


1

2

3

logger.addHandler(ch)#添加handler

logger.removeHandler(ch) #删除handler

⑤Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical()

说明:可以设置的日志级别


1

2

3

4

5

logger.debug(‘debug message‘)

logger.info(‘info message‘)

logger.warn(‘warn message‘)

logger.error(‘error message‘)

logger.critical(‘critical message‘)

⑥获取handler个数


1

2

3

4

5

handler_len = len(logger.handlers)

print(handler_len)

#输出

1

2)、handler

  handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler

①Handler.setLevel(lel)

说明:指定被处理的信息级别,低于lel级别的信息将被忽略。


1

2

ch = logging.StreamHandler()

ch.setLevel(logging.DEBUG)

②Handler.setFormatter()

说明:给这个handler选择一个格式


1

2

3

ch_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"#生成格式,具体需要什么格式看需求

ch.setFormatter(ch_formatter) #设置格式

③Handler.addFilter(filt)、Handler.removeFilter(filt)

说明:新增或删除一个filter对象

四、handler详解

1、logging.StreamHandler

说明:使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息,也就是屏幕输出。

它的构造函数是:StreamHandler([strm]),其中strm参数是一个文件对象,默认是sys.stderr。具体用法看下面代码:

import logging
logger = logging.getLogger("TEST-LOG")
logger.setLevel(logging.DEBUG)

ch = logging.StreamHandler() #创建一个StreamHandler对象
ch.setLevel(logging.DEBUG) #设置输出StreamHandler日志级别

ch_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")   #格式
ch.setFormatter(ch_formatter)     #传入格式参数
logger.addHandler(ch)       #增加handler

logger.info(‘info message‘)
logger.warn(‘warn message‘)
logger.error(‘error message‘)
logger.critical(‘critical message‘)

# 输出
#2018-01-28 21:15:02,112 - TEST-LOG - INFO - info message
#2018-01-28 21:15:02,112 - TEST-LOG - WARNING - warn message
#2018-01-28 21:15:02,112 - TEST-LOG - ERROR - error message
#2018-01-28 21:15:02,112 - TEST-LOG - CRITICAL - critical message

2、logging.FileHandler

说明:和StreamHandler类似,用于向一个文件输出日志信息,不过FileHandler会帮你打开这个文件。

它的构造函数是:FileHandler(filename[,mode])。filename是文件名,必须指定一个文件名。mode是文件的打开方式。参见Python内置函数open()的用法。默认是’a‘,即添加到文件末尾。用法看下面代码:

import logging

#create logging
logger = logging.getLogger("TEST-LOG")
logger.setLevel(logging.DEBUG)

fh = logging.FileHandler("debug.log",encoding="utf-8") #日志输出到debug.log文件中
fh.setLevel(logging.INFO) #设置FileHandler日志级别

fh_formatter = logging.Formatter("%(asctime)s %(module)s:%(levelname)s %(message)s")

fh.setFormatter(fh_formatter)

logger.addHandler(fh)

logger.info(‘info message‘)
logger.warning(‘warning message‘)
logger.error(‘error message‘)
logger.critical(‘critical message‘)

#文件debug.log里的输出:
#2018-01-28 21:19:45,221 logging文件输出:INFO info message
#2018-01-28 21:19:45,221 logging文件输出:WARNING warning message
#2018-01-28 21:19:45,221 logging文件输出:ERROR error message
#2018-01-28 21:19:45,221 logging文件输出:CRITICAL critical message

3、logging.handlers.RotatingFileHandler

说明:这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建 一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把 文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。

它的构造函数是:RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]]),其中filename和mode两个参数和FileHandler一样。

maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。

backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。

 用法看下面代码:

import logging
from logging import handlers  #需要导入handlers

logger = logging.getLogger(__name__)
log_file = "timelog.log"

#按文件大小来分割,10个字节maxBytes,保留个数是3个
fh=handlers.RotatingFileHandler(filename=log_file,maxBytes=10,backupCount=3,encoding="utf-8")
formatter = logging.Formatter(‘%(asctime)s %(module)s: %(message)s‘)
fh.setFormatter(formatter)
logger.addHandler(fh)

logger.warning("test11")
logger.warning("test12")
logger.warning("test13")
logger.warning("test14")
logger.warning("test15")
#文件的结果就是
#timelog.log     2018-01-28 21:31:38,513 logging文件个数保留: test15
#timelog.log1   2018-01-28 21:31:38,500 logging文件个数保留: test14
#timelog.log2    2018-01-28 21:31:38,487 logging文件个数保留: test13
#timelog.log3    2018-01-28 21:31:38,471 logging文件个数保留: test12

4、logging.handlers.TimedRotatingFileHandler

说明:这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。

它的构造函数是:TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]]),其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。

interval是时间间隔。when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值:①S:秒②M:分③H:小时④D:天⑤W :每星期(interval==0时代表星期一)⑥midnight:每天凌晨

5、控制台和文件日志共同输出

需要什么样的输出,只需要添加相应的handler就ok了。

逻辑图:

代码如下:

import logging

#create logging
logger = logging.getLogger("TEST-LOG")
logger.setLevel(logging.DEBUG)

#屏幕handler
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
#文件handler
fh = logging.FileHandler("debug.log",encoding="utf-8")
fh.setLevel(logging.INFO)
#分别创建输出日志格式
ch_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
fh_formatter = logging.Formatter("%(asctime)s %(module)s:%(levelname)s %(message)s")
#设置handler的输出格式
ch.setFormatter(ch_formatter)
fh.setFormatter(fh_formatter)
#添加handler
logger.addHandler(ch)
logger.addHandler(fh)

# ‘application‘ code
logger.debug(‘debug message‘)
logger.info(‘info message‘)
logger.warn(‘warn message‘)
logger.error(‘error message‘)
logger.critical(‘critical message‘)

 注:如果添加时间分割或者文件大小分割,再修改上述代码写入文件的handler即可。

五、运用模板做日记功能

  了解记住上面的流程,我们来做一个简单的日记配置(此方法高能)

"""
logging配置
"""

import os
import logging.config

# 定义三种日志输出格式 开始

standard_format = ‘[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]‘                   ‘[%(levelname)s][%(message)s]‘ #其中name为getlogger指定的名字

simple_format = ‘[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s‘

id_simple_format = ‘[%(levelname)s][%(asctime)s] %(message)s‘

# 定义日志输出格式 结束

logfile_dir = os.path.dirname(os.path.abspath(__file__))  # log文件的目录

logfile_name = ‘all2.log‘  # log文件名

# 如果不存在定义的日志目录就创建一个
if not os.path.isdir(logfile_dir):
    os.mkdir(logfile_dir)

# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)

# log配置字典
LOGGING_DIC = {
    ‘version‘: 1,
    ‘disable_existing_loggers‘: False,    #前面两个暂时不关注
    ‘formatters‘: {
        ‘standard‘: {
            ‘format‘: standard_format
        },
        ‘simple‘: {
            ‘format‘: simple_format
        },
    },
    ‘filters‘: {},
    ‘handlers‘: {
        #打印到终端的日志
        ‘console‘: {
            ‘level‘: ‘DEBUG‘,
            ‘class‘: ‘logging.StreamHandler‘,  # 打印到屏幕
            ‘formatter‘: ‘simple‘
        },
        #打印到文件的日志,收集info及以上的日志
        ‘default‘: {
            ‘level‘: ‘DEBUG‘,
            ‘class‘: ‘logging.handlers.RotatingFileHandler‘,  # 保存到文件
            ‘formatter‘: ‘standard‘,
            ‘filename‘: logfile_path,  # 日志文件
            ‘maxBytes‘: 1024*1024*5,  # 日志大小 5M
            ‘backupCount‘: 5,
            ‘encoding‘: ‘utf-8‘,  # 日志文件的编码,再也不用担心中文log乱码了
        },
    },
    ‘loggers‘: {
        #logging.getLogger(__name__)拿到的logger配置
        ‘‘: {     #这里可以匹配相同的key,然后输出,还有空,默认都可以输出
            ‘handlers‘: [‘default‘, ‘console‘],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            ‘level‘: ‘DEBUG‘,
            ‘propagate‘: True,  # 向上(更高level的logger)传递
        },
    },
}

def load_my_logging_cfg():
    logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
    logger = logging.getLogger(__name__)  # 生成一个log实例
    logger.info(‘It works!‘)  # 记录该文件的运行状态

if __name__ == ‘__main__‘:
    load_my_logging_cfg()

原文地址:https://www.cnblogs.com/ManyQian/p/8728558.html

时间: 2024-08-02 04:03:40

python全栈开发-logging模块(日记专用)的相关文章

Python全栈开发--socketserver模块和验证客户端链接的合法性

验证客户端链接的合法性 分布式系统中实现一个简单的客户端链接认证功能 #_*_coding:utf-8_*_ from socket import * import hmac,os secret_key=b'linhaifeng bang bang bang' def conn_auth(conn): ''' 认证客户端链接 :param conn: :return: ''' print('开始验证新链接的合法性') msg=os.urandom(32) conn.sendall(msg) h=

Python全栈开发——时间模块和随机模块

#时间模块 import time import datetime print(datetime.datetime.now()) #时间戳 print(time.time()) #将时间戳转化为结构化时间 print(time.localtime(time.time())) #将结构化时间转化为时间戳 print(time.mktime(time.localtime())) #将结构化时间转化为字符串时间 strftime print(time.strftime("%Y---%m-%d %X&q

Python全栈开发【第一篇】:初识Python

Python全栈开发[第一篇] 本节内容: Python 的种类 Python 的环境 Python 入门(解释器.编码.变量.input输入.if流程控制与缩进.while循环) if流程控制与while循环练习题 基本数据类型前引 Python 的种类 Cpython Python的官方版本,使用C语言实现,使用最为广泛,CPython实现会将源文件(py文件)转换成字节码文件(pyc文件),然后运行在Python虚拟机上. Jyhton Python的Java实现,Jython会将Pyth

python全栈开发目录

python全栈开发目录 linux命令 初识python python基础数据类型 函数编程.set.深浅拷贝 内置函数 文件操作 装饰器 迭代器和生成器 常用模块 初识类和对象 类和对象(进阶) 反射 异常处理 socket.IO多路复用 线程.进程.协程 HTML CSS JavaScript DOM文档操作 jQuery实例 web框架本质 Tornado mysql基础 mysql进阶 ..... 基本算法 递归--二分法查找 冒泡排序 更多 线程池

Python 全栈开发【第一篇】:目录

Python 全栈开发[第0篇]:目录 第一阶段:Python 开发入门 Python 全栈开发[第一篇]:计算机原理&Linux系统入门 Python 全栈开发[第二篇]:Python基础语法入门 Python 全栈开发[第三篇]:数据类型.字符编码.文件操作 第二阶段:函数编程&常用标准库 Python 全栈开发[第四篇]:函数.递归.生成器.迭代器 Pyhton 全栈开发[第五篇]:常用模块学习 第三阶段:面向对象编程&网络编程基础 Python 全栈开发[第六篇]:面向对象

python全栈开发学习目录

python全栈开发学习目录 第一章 计算机基础 第二章Python入门 第三章数据类型 第四章文件操作 第五章函数 第六章 模块 第七章 面向对象 第八章 网络编程 第九章 并发编程 第十章 数据库 第十一章 前端开发-html 第十一章 前端开发-css 附加:js特效 15个小demo 第十一章 前端开发-JavaScript 第十一章 前端开发-jQuery 第十一章 前端开发-bootstrap 第十二章 Django框架开发 ... 原文地址:https://www.cnblogs.

Python全栈开发【基础三】

Python全栈开发[基础三]  本节内容: 函数(全局与局部变量) 递归 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 1 def 函数名(参数): 2 3 ... 4 函数体 5 ... 6 返回值 函数的定义主要有如下要点: def:表示函数的关键字 函数名:函数的名称,日后根据函数名调用函数 函数体:函数中进行一系列的逻辑计算 参数:为函数体提供数据 返回值:当函数执行完毕后,可以给调用者返回数据. 总结使用函数的好处: 1.减少代码重用 2.保持一致性,易维护

Python全栈开发

Python全栈开发 一文让你彻底明白Python装饰器原理,从此面试工作再也不怕了. 一.装饰器 装饰器可以使函数执行前和执行后分别执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator),装饰器的功能非常强大,但是理解起来有些困难,因此我尽量用最简单的例子一步步的说明这个原理. 1.不带参数的装饰器 假设我定义了一个函数f,想要在不改变原来函数定义的情况下,在函数运行前打印出start,函数运行后打印出end,要实现这样一个功能该怎么实现?看下面如何用

Python全栈开发【基础二】

Python全栈开发[基础二] 本节内容: Python 运算符(算术运算.比较运算.赋值运算.逻辑运算.成员运算) 基本数据类型(数字.布尔值.字符串.列表.元组.字典) 编码与进制转换 Python 运算符 1.算术运算: 2.比较运算: 3.赋值运算: 4.逻辑运算:  5.成员运算: 基本数据类型 1.数字 int(整型) 1 class int(object): 2 """ 3 int(x=0) -> integer 4 int(x, base=10) -&g