Python logging日志模块 配置文件方式
在一些微服务或web服务中我们难免需要日志功能,用来记录一些用户的登录记录,操作记录,以及一些程序的崩溃定位,执行访问定位等等;
Python内置非常强大的日志模块==>logging今天给大家分享一下以配置文件形式进行配置log日志;
Centos6.7
Python3.6
logging0.5.1.2
logging模块有三个比较重要的功能组件:
1、loggers配置文件可定义一些输出日志的appname
2、handler过滤器,比如设置日志的分隔大小,输出位置,日志文件创建等
3、formatters指定日志输出的格式
1:创建一个文件,以.conf结尾或以.ini结尾(PS:其他的结尾没试过,你可以试试)
vimlog.conf
2:定义日志输出的APP名,指定过滤器这里用loggers功能
[loggers]#固定写法 keys=root,error,info#创建三个app名,root是父类,必需存在的 [logger_root]#创建完的app名我们要定义一些规则,严格要求格式为"logger_appname" level=DEBUG#设置日志级别 qualname=root#这里在"root"appname下可以不填,所有没获取get的情况下默认app名都是root handlers=debugs#设置指定过滤器,多个以逗号分隔,这个名字待会儿我们会以固定格式"handler_(value)"创建 [logger_error] level=ERROR qualname=error#除了rootappname以外,定义的app名必须要设置这个属性,用于定义打印输出时候的app名 handlers=errors [logger_info] level=INFO qualname=INFO handlers=infos
3:定义日志过滤器这里用handler功能
[handlers]#固定格式
keys=infos,errors,debugs#定义过滤器名称,下面定义以handler_keysname格式定义,上面引用名称必须和keys一致
[handler_infos]
class=FileHandler#指定过滤器组件,详情请看官网,这个是以文件方式创建
level=INFO#设置级别
formatter=form01#定义日志打印格式,下面会创建formatters,格式也是严格要求formatter_keysname创建
args=('info.log','a')#创建文件名字,以什么方式打开
[handler_errors]
class=FileHandler
level=DEBUG
formatter=form02
args=('info1.log','a')
[handler_debugs]
class=FileHandler
level=DEBUG
formatter=form02
args=('info1.log','a')
3:定义日志输出格式,这里我们介绍最后一个组件formatters
[formatters]#固定格式 keys=form01,form02#定义名称,下面会引用格式同上 [formatter_form01] format=%(asctime)s%(filename)s%(levelname)s%(message)s#年-月-日时-分-秒,毫秒,文件名,级别名,消息信息 datefmt=%Y-%m-%d%H:%M:%S#日期输出格式 [formatter_form02] format=%(asctime)s%(filename)s%(levelname)s%(message)s datefmt=%Y-%m-%d%H:%M:%S
4:具体程序引用
#!/usr/bin/envpython
importlogging
importlogging.config
logging.config.fileConfig('log.conf')
logs=logging.getLogger('error')
logs.error('errorsssss')
补充知识:python按照日志等级将日志输出至不同的日志文件
将日志按照等级分别保存在不同的文件中,并在控制台同步输出。
importos
importsys
importlogging
fromlogs.multiprocessloghandlerimportMultiprocessHandler
defloggerDefine(platform,log_name):
base_dir="F:\PythonProject\\xiao_new_resources\logs"
info_dir_path=base_dir+"\\info\\{}".format(platform)
error_dir_path=base_dir+"\\error\\{}".format(platform)
#判断响应的文件是否存在
ifnotos.path.exists(info_dir_path):
os.makedirs(info_dir_path)
info_dir=os.path.join(info_dir_path,log_name)
ifnotos.path.exists(error_dir_path):
os.makedirs(error_dir_path)
error_dir=os.path.join(error_dir_path,log_name)
#返回一个logger对象,如果没有指定名字将返回rootlogger
log=logging.getLogger('test')
#定义日志输出格式
formattler='%(asctime)s|%(processName)s|%(threadName)s|%(levelname)s|%(filename)s:%(lineno)d|%(funcName)s|%(message)s'
fmt=logging.Formatter(formattler)
#设置日志控制台输出
stream_handler=logging.StreamHandler(sys.stdout)
stream_handler.setLevel(logging.INFO)
#设置控制台文件输出
log_handler_info=MultiprocessHandler(info_dir)
log_handler_err=MultiprocessHandler(error_dir)
#设置日志输出格式:
stream_handler.setFormatter(fmt)
log_handler_info.setFormatter(fmt)
log_handler_err.setFormatter(fmt)
#设置过滤条件
info_filter=logging.Filter()
info_filter.filter=lambdarecord:record.levelno=logging.WARNING
#对文件输出日志添加过滤条件
log_handler_info.addFilter(info_filter)
log_handler_err.addFilter(err_filter)
#对logger增加handler日志处理器
log.addHandler(log_handler_info)
log.addHandler(log_handler_err)
log.addHandler(stream_handler)
log.setLevel("INFO")
returnlog
if__name__=='__main__':
logg=loggerDefine("youtube","youtube.log")
logg.info("info")
logg.warning("warning")
logg.error("error")
multiprocessloghandler源码:
importdatetime
importlogging
importos
importre
try:
importcodecs
exceptImportError:
codecs=None
classMultiprocessHandler(logging.FileHandler):
"""支持多进程的TimedRotatingFileHandler"""
def__init__(self,filename,when='D',backupCount=7,encoding="utf-8",delay=False):
"""
filename日志文件名,when时间间隔的单位,backupCount保留文件个数
delay是否开启OutSteam缓存
True表示开启缓存,OutStream输出到缓存,待缓存区满后,刷新缓存区,并输出缓存数据到文件。
False表示不缓存,OutStrea直接输出到文件
"""
self.prefix=filename
self.backupCount=backupCount
self.when=when.upper()
#正则匹配年-月-日
#正则写到这里就对了
self.extMath=r"\d{4}-\d{2}-\d{2}"
#S每秒建立一个新文件
#M每分钟建立一个新文件
#H每天建立一个新文件
#D每天建立一个新文件
self.when_dict={
'S':"%Y-%m-%d-%H-%M-%S",
'M':"%Y-%m-%d-%H-%M",
'H':"%Y-%m-%d-%H",
'D':"%Y-%m-%d"
}
#日志文件日期后缀
self.suffix=self.when_dict.get(when)
#源码中self.extMath写在这里
#这个正则匹配不应该写到这里,不然非D模式下会造成self.extMath属性不存在的问题
#不管是什么模式都是按照这个正则来搜索日志文件的。
#ifself.when=='D':
#正则匹配年-月-日
#self.extMath=r"^\d{4}-\d{2}-\d{2}"
ifnotself.suffix:
raiseValueError(u"指定的日期间隔单位无效:%s"%self.when)
#拼接文件路径格式化字符串
self.filefmt=os.path.join(os.getcwd(),"%s.%s"%(self.prefix,self.suffix))
a="%s.%s"%(self.prefix,self.suffix)
#使用当前时间,格式化文件格式化字符串
self.filePath=datetime.datetime.now().strftime(self.filefmt)
#获得文件夹路径
_dir=os.path.dirname(self.filefmt)
try:
#如果日志文件夹不存在,则创建文件夹
ifnotos.path.exists(_dir):
os.makedirs(_dir)
exceptException:
print("创建文件夹失败")
print("文件夹路径:"+self.filePath)
pass
ifcodecsisNone:
encoding=None
#调用FileHandler
logging.FileHandler.__init__(self,self.filePath,'a+',encoding,delay)
defshouldChangeFileToWrite(self):
"""更改日志写入目的写入文件
returnTrue表示已更改,False表示未更改"""
#以当前时间获得新日志文件路径
_filePath=datetime.datetime.now().strftime(self.filefmt)
#新日志文件日期不等于旧日志文件日期,则表示已经到了日志切分的时候
#更换日志写入目的为新日志文件。
#例如按天(D)来切分日志
#当前新日志日期等于旧日志日期,则表示在同一天内,还不到日志切分的时候
#当前新日志日期不等于旧日志日期,则表示不在
#同一天内,进行日志切分,将日志内容写入新日志内。
if_filePath!=self.filePath:
self.filePath=_filePath
returnTrue
returnFalse
defdoChangeFile(self):
"""输出信息到日志文件,并删除多于保留个数的所有日志文件"""
#日志文件的绝对路径
self.baseFilename=os.path.abspath(self.filePath)
#stream==OutStream
#streamisnotNone表示OutStream中还有未输出完的缓存数据
ifself.stream:
#self.stream.flush()
self.stream.close()
self.stream=None
#delay为False表示不OutStream不缓存数据直接输出
#所有,只需要关闭OutStream即可
ifnotself.delay:
#self.stream.close()
self.stream=self._open()
#删除多于保留个数的所有日志文件
ifself.backupCount>0:
forsinself.getFilesToDelete():
#prints
os.remove(s)
defgetFilesToDelete(self):
"""获得过期需要删除的日志文件"""
#分离出日志文件夹绝对路径
#split返回一个元组(absFilePath,fileName)
#例如:split('I:\ScripPython\char4\mybook\util\logs\mylog.2017-03-19)
#返回(I:\ScripPython\char4\mybook\util\logs,mylog.2017-03-19)
#_表示占位符,没什么实际意义,
dirName,_=os.path.split(self.baseFilename)
fileNames=os.listdir(dirName)
result=[]
#self.prefix为日志文件名列如:mylog.2017-03-19中的mylog
#加上点号.方便获取点号后面的日期
prefix=self.prefix
prefix=_.rsplit(".",1)[0]+"."
plen=len(prefix)
forfileNameinfileNames:
iffileName[:plen]==prefix:
#日期后缀mylog.2017-03-19中的2017-03-19
suffix=fileName[plen:]
#匹配符合规则的日志文件,添加到result列表中
ifre.compile(self.extMath).match(suffix):
result.append(os.path.join(dirName,fileName))
result.sort()
#返回待删除的日志文件
#多于保留文件个数backupCount的所有前面的日志文件。
iflen(result)
以上这篇Pythonlogging日志模块配置文件方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。