day18 规范目录 logging
1.规范目录结构
使用规范结构目录的好处
-使项目结构更清晰
-提高可读性
规范目录结构不是固定的,可以根据实际需求进行添加修改
常见目录如下:
conf(config) 存放配置文件
db 存放数据处理相关
bin 存放执行文件
lib(commo) :存放公共代码和第三方模块
core:(存放核心业务逻辑)
log:存储输出日志
readme:是一个文本文件,用于描述应用程序
如果你的执行文件不在最外层,name需要手动将要访问的模块路径加入到sys.path
import sys
sys.path.append(r'文件跟目录')#一般不用
__file__ (获取当前执行文件的完整路径)
BASE_DIR=os.path.dirname(os.path.dirname(__file__))
sys.path.append(BASE_DIR)
2.常用模块
loggin日志模块
什么是日志?
就像生活中的日记 用于记录什么时间发生了什么事情
为什么要记?
为了在以后程序出现问题的时候,能通过日志来找到问题的原因
怎么记日志
可以自己实现 当然有功能更强大的longing模块
logging模块将日志分为了五种级别
为什么要分级别?是为了在后期查看日志时候方便定位
logging的默认显示级别是WARNING,低于WARNING级别的都不会显示
默认的输出位置是终端
默认的输出格式 WARNING(级别):root(日志生成器名字):warning(输出的日志消息)
修改默认的行为
日志模块的四种角色
'''
logger 日志生成器 生成一条日志(可以设置生成日志的级别)
filter 日志过滤器 对logger生成的日志进行(面向对象)
formatter格式化器 设置日志的输出格式
handler 处理器 最终将日志输出到指定位置(也可以设置输出的日志级别)
'''
流程如下:
1.获取生成器
2.格式处理器
3.创建handler处理器
(可以绑定多个handler Streamhandler 输出到终端)
4.将handler与格式处理器绑定
5.把handler生成器绑定
import logging
loger=logging.getLogger('logger1')
#设置日志级别
#loggingm模块内部使用整数区分级别
#此处可以直接写对应整数 但是建议写常量
loger.setLevel(logging.WARNING)
logging.warning('这是一个警告')
#创建一个处理器
handler=logging.FileHandler('tset.log','a',encoding='utf-8')
logging.FileHandler
fmt=logging.Formatter('%(asctime)s %(funcName)s %(message)s')
handler.setFormatter(fmt)
#将handler与生成器绑定
#可以为一个生成器指定多个处理器
loger.addHandler(handler)
loger.error('这是一个错误信息')
使用格式
%(name)s: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:用户输出的消息
使用字典配置
import logging.config
logging.config.dictconfig()
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_path = "dd.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配置
'': {
'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'level': 'DEBUG',
'propagate': True, # 向上(更高level的logger)传递
},
},
}
import os
os.path.dirname()获取该路径的上一级路径