Python logging 日志模块

简单使用

import logging
logging.warning("test log")

这行代码会在 控制台 输出 “ WARNING:root:test log”。
但,众所周知,日志是有级别的。
logging的默认级别是 warning,所以如果直接输入 longging.info(“test info”),控制台是不会有输出的。

设置默认日志级别

import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug("test debug log")

将日志级别设置为 debug,所以控制台会有输出

输出到文件

import logging
logging.basicConfig(filename="test.log")
logging.warning("test filelog")

此时,控制台不再有输出,而是输出到 test.log 文件。

import logging
logging.basicConfig(filename="test.log",level=logging.DEBUG)
logging.debug("test debug file log")

debug 日志写入 文件 test.log

日志格式化输出

默认格式是 “%(levelname)s:%(name)s:%(message)s”

import logging
logging.basicConfig(format="%(asctime)s - %(levelname)s - %(name)s : %(message)s")
logging.warning("test format message")

还可额外指定 时间格式:
logging.basicConfig(format=”%(asctime)s - %(levelname)s - %(name)s : %(message)s”, datefmt=”%x %x “)

以上足够满足简单的开发日志使用了。


logging 模块提供了四大组件:logger、handler、format、filter,用来满足一些高级需求。
logger 是日志接口、写日志时就用它。logging.info() 这个方法实际上用的是 默认的 logger, logging可以有多个 logger。
每个 logger 有对应的 handler 时,才会输出日志。logger 可以有多个 handler。
handler 可以设置输出格式 format、级别、和过滤器 filter。
logger 和 handler 是 多对多 关系。

只有 logger 是真正被调用的,其他三项都可以说是配置项,在初始化日志模块的时候配置好就可以了。

logger

testlogger = logging.getLogger(“testlogname”)

这是获取 logger 对象的方法,当 “testlogname” 不存在时,会创建一个新的 logger 并返回,否则返回已有的 logger。这跨模块的 logger 的基础。
logger 的名字可任意取,但最好用 . 分割层级,以便 logging 在层级间传递日志。
例如:myApp.myModule.myFile

myAppLog = logging.getLogger(“myApp”) 
myModuleLog = logging.getLogger(“myApp.myModule”) 
myFileLog = logging.getLogger(“myApp.myModule.myFile”)
#再写入日志
myAppLog.warning("my app log")
myModuleLog .warning("my modulelog")
myFileLog .warning("my file log") 

此时,”my app log” 只会写入 myAppLog,”my modulelog” 写入 myModuleLog 和 myAppLog,”my file log” 写入 myFileLog 、myModuleLog 、和 myAppLog。

以上是伪码,后续有完整代码。

handler 、format

光生成了 logger 其实还无法输出日志的,logger 只有与 handler 绑定了,才会有输出,handler 定义了输出的 目的地(控制台、文件、网络、邮件等)、格式、级别、过滤器等
例如,创建一个输出到文件的 handler:

filehandler = logging.FileHandler("file.log")
# 设置 handler 的输出级别
filehandler.setLevel(logging.DEBUG)
# 设置 handler 的输出格式
fileformatter = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s : %(message)s")
filehandler.setFormatter(fileformatter)
# 将 logger 关联 handler
logger.addHandler(filehandler)
# 然后 logger 输入的日志,就通过 filehandler 写入文件 file.log 了。
logger.info("a file log")

logger 和 handler

一个 logger、可以输出到 多个 handler。
一个 handler、可以接受多个 logger 的输出。

import logging
# 创建 有父子关系 的 logger,loggerFather -> loggerChild ,设置级别
loggerFather = logging.getLogger("fatherlog")
loggerChild = logging.getLogger("fatherlog.childlog")
loggerFather .setLevel(logging.DEBUG)
loggerChild .setLevel(logging.DEBUG)
#再创建两个 文件 handler,分别设置级别和 format
fatherhandler = logging.FileHandler("father.log")
childhandler = logging.FileHandler("child.log")
fatherhandler.setLevel(logging.DEBUG)
childhandler.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s : %(message)s")
# 将父子 logger 分别提添加 对应的 handler
loggerFather.addHandler(fatherhandler)
loggerChild .addHandler(childhandler)
# 写入日志
loggerFather.debug("test father log")
loggerChild .debug("test child log")
# 打开 father.log ,既有 loggerFather 的日志,也有 loggerChild 的日志
# 打开 child.log,只有 loggerChild 的日志

# logger/handler 多对多关系测试。再创建另一个 logger,同时添加 fatherhandler 、childhandler 
loggerother = logging.getLogger("otherlog") 
loggerother.setLevel(logging.DEBUG)
loggerother.addHandler(fatherhandler)
loggerother.addHandler(childhandler )
loggerother.debug("test other log")
# father.log 和 child.log 都有 loggerother 的日志。

时间自动切片

import logging
import logging.handlers
logger = logging.getLogger('mylover')
logger .setLevel(logging.DEBUG)
format = logging.Formatter(fmt="%(asctime)s-%(levelname)s-%(name)s-%(message)s", datefmt="%x %X")
handler = logging.handlers.TimedRotatingFileHandler('test.log', when='D', interval=1,backupCount=30)
handler.setFormatter(format )
handler.setLevel(logging.DEBUG)
logger.addHandler(handler )

TimedRotatingFileHandler(‘test.log’, when=’D’, interval=1,backupCount=30)
when=’D’:表示按天计算时间间隔
interval=1:表示 1 个 when 之后就进行切片
backupCount=30:表示最多保留 30 个历史日志切片文件


至此,满足大多数 product 场景的日志功能。拿来主义,就此打住。
但是,logging 还有其他的功能,打住只不过是不继续深究而已,logging 还能做哪些事情仍然需要有所了解。
1、日志配置从文件读取
2、自定义日志级别
3、日志自动分片
4、build-in handler
● 控制台 handler
● 大小自动分片 handler
● 邮件 handler
● http handler
● syslog handler
……

附一个我在用的 flask log 配置:

import logging
applogger = logging.getLogger('myApp')
apploggerformat = logging.Formatter(fmt="%(asctime)s-%(levelname)s-%(name)s-%(message)s", datefmt="%x %X")
apploggerhandler = logging.handlers.TimedRotatingFileHandler('/var/log/myApp/myApp.log', when='D', interval=1,backupCount=30)
apploggerhandler.setFormatter(apploggerformat)
if app.debug:
    apploggerhandler.setLevel(logging.DEBUG)
    applogger.setLevel(logging.DEBUG)
else:
    apploggerhandler.setLevel(logging.WARNING)
    applogger.setLevel(logging.WARNING)

loggers = [applogger, app.logger, logging.getLogger('sqlalchemy')]
[logger.addHandler(apploggerhandler) for logger in loggers]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值