Django使用python自带的logging 作为日志打印工具。简单介绍下logging。
logging 是线程安全的,其主要由4部分组成:
Logger
用户使用的直接接口,将日志传递给Handler
Handler
控制日志输出到哪里,console,file…
一个logger可以有多个Handler
Filter
控制哪些日志可以从logger流向Handler
Formatter
控制日志的格式
用户使用logging.getLogger([name])获取logger实例。
如果没有名字,返回logger层级中的根logger(root logger)。以相同名字调用该函数总是返回同一个logger实例。这意味着logger实例不需要在应用的各个部分之间传来传去。
Django通过在settings文件中使用LOGGING来定制日志输出(包括定义logger, handler, formatter等)
1,logging模块的最简单直接的使用方法
import logging
logging.debug("debug")
logging.info("info")
logging.warning("warning")
logging.error("error")
执行上面代码将输出
WARNING:root:warning
ERROE:root:error
原因是因为 python 默认等级是warning,所以只会输出上面两个,而不会输出debug和info信息
2- 使用logging.basicConfig()打印信息到控制台
import logging
logging.basicConfig(format="%(asctime)s- %(pathname)s[line:%(lineno)d]- %(levelname)s: %(message)s", level=logging.DEBUG)
logging.debug("debug")
logging.info("info")
logging.warning("warning")
logging.error("error")
logging.critical("critical")
输出格式: -- 2019-05-29 14:32:10,138- C:/Users/Desktop/project/*****.py[line:12]- DEBUG: debug
# 3 - 使用logging.basciConfig()保存log文件
import logging
logging.basicConfig(level=logging.ERROR, # 保存日志级别
filename="test.log", # 保存日志文件名
filemode="a", # 指定日志写入文件模式,“a”代表追加写,“w”会覆盖原来日志
format="%(asctime)s -%(pathname)s[line:%(lineno)d]- %(levelname)s: %(message)s" # 日志格式
)
logging.debug("debug")
logging.info("info")
logging.error("error")
logging.warning("warning")
logging.critical("critical")
# 4- 既往屏幕输入,又往文件写入
import logging
from logging import handlers
class Logger(object):
level_relations = {
'debug':logging.DEBUG,
'info':logging.INFO,
'warning':logging.WARNING,
'error':logging.ERROR,
'crit':logging.CRITICAL
}
def __init__(self, filename, level='info', when='D', backCount=3,
fmt='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'):
self.logger = logging.getLogger(filename)
format_str = logging.Formatter(fmt) # 设置日志格式
self.logger.setLevel(self.level_relations.get(level)) # 设置日志级别
sh = logging.StreamHandler() # 往屏幕上输出
sh.setFormatter(format_str) # 设置屏幕上显示的格式
th = handlers.TimedRotatingFileHandler(filename=filename, when=when, backupCount=backCount,
encoding='utf-8') # 往文件里写入#指定间隔时间自动生成文件的处理器
# 实例化TimedRotatingFileHandler
# interval是时间间隔,backupCount是备份文件的个数,如果超过这个个数,就会自动删除,when是间隔的时间单位,单位有以下几种:
# S 秒
# M 分
# H 小时、
# D 天、
# W 每星期(interval==0时代表星期一)
# midnight 每天凌晨
th.setFormatter(format_str) # 设置文件里写入的格式
self.logger.addHandler(sh) # 把对象加到logger里
self.logger.addHandler(th)
if __name__ == '__main__':
log = Logger("all.log", level="debug")
log.logger.debug("debug")
log.logger.info("info")
log.logger.warning("warning")
log.logger.error("error")
log.logger.critical("critical")
Logger("error.log", level="error").logger.error("error")
在程序中的使用最简单直接的方法
import logging
logging.basicConfig(filename="logging_test1.log", filemode="a", format="%(asctime)s %(name)s: %(levelname)s:%(message)s", datefmt="%Y-%m-%d %H:%M:%S", level=logging.INFO)
a = 5
b = 0
try:
c = a / b
except Exception as e:
# 下面三种选哪一种都可以, 但是后面两种要加上 exc_info=True,否则不会记录错误具体原因, 使用第三种必须要加上日志级别
logging.exception("Exception occurred")
logging.error("Exception occurred", exc_info=True)
logging.log(level=logging.INFO, msg="Exception occurred", exc_info=True)
这里要额外说一下当自己已经 自定义了logger,就不要再使用logging中的日志输出的方法了
# 创建了自定义的 Logger 对象,就不要在用 logging 中的日志输出方法了,这些方法使用的是默认配置的 Logger 对象,否则会输出的日志信息会重复。
import logging
import logging.handlers
logger = logging.getLogger("logger")
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.debug("This is a customer debug message")
# 下面这一行是logging自己记录日志的方法
#logging.info("This is an customer info message")
logger.warning("This is a customer warning message")
logger.error("This is an customer error message")
logger.critical("This is a customer critical message")
最后是在django中一般配置的信息
LOGGING = {
'version': 1, # 必须指定为1
'disable_existing_loggers': False, # 禁用默认配置中的所有logger
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(funcName)s %(lineno)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
},
},
'filters': {
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
'level': 'DEBUG',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(os.path.dirname(os.path.dirname(BASE_DIR)), "logs/***.log"), # 日志文件的位置
'maxBytes': 300 * 1024 * 1024, #每个日志文件大小
'backupCount': 10, # 日志文件个数
'formatter': 'verbose'
},
},
'loggers': {
'django': { # 定义了一个名为django的日志器
'handlers': ['console', 'file'],
'propagate': True,
'level': 'INFO'
},
}
}