Python 的常用模块 5
最编程
2024-07-12 11:47:33
...
一、日志模块,logging模块
1)logging模块简单使用,屏幕输出。默认级别30
import logging logging.debug('debug...') # 10 logging.info('info....') #20 logging.warning('可能着火...') #30 logging.error('着火啦快跑') # 40 logging.critical('火越烧越大') #50
2)控制日志输出到文件,但屏幕显示信息会消失。注意,存入文件时是以gbk,所以打开时,也要指定gbk格式
import logging # 控制日志输出 logging.basicConfig( filename='access.log', # 记录在当前目录,生成文件 format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', # 时间 日志的名,如debug,error 级别 模块 # 接收的信息 datefmt='%Y-%m-%d %H:%M:%S %p', # 时间 level=20, ) logging.debug('debug...') # 10 logging.info('info....') #20 logging.warning('可能着火...') #30 logging.error('着火啦快跑') # 40 logging.critical('火越烧越大') #50
3)日志模块调用原理
import logging #logger对象:用来产生日志 logger1=logging.getLogger('银行业务相关') # 日志名是用告诉我们所记录的日志到底是属于哪一类业务相关的信息 #filter对象:过滤日志 #handler对象:控制日志的去向: 文件 或 终端 fh1=logging.FileHandler('a1.log',encoding='utf-8') fh2=logging.FileHandler('a2.log',encoding='utf-8') ch=logging.StreamHandler() #代表的就是终端 # 建立logger对象与handler对象的绑定关系 logger1.addHandler(fh1) logger1.addHandler(fh2) logger1.addHandler(ch) #formmatter对象:定制日志的格式 formatter1=logging.Formatter( fmt='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p' ) formatter2=logging.Formatter( fmt='%(asctime)s ===> %(message)s', ) # 为handler对象绑定日志格式 fh1.setFormatter(formatter1) fh2.setFormatter(formatter2) ch.setFormatter(formatter2) #设置日志级别:两层关卡,第一次是logger,第二层是handler,只有两层都放行,最终日志才会打印 # logger1.setLevel(50) # fh1.setLevel(10) # fh2.setLevel(10) # ch.setLevel(10) logger1.setLevel(10) fh1.setLevel(10) fh2.setLevel(10) ch.setLevel(10) # 调用logger对象产生日志 logger1.debug('这是一条debug日志')
4)引用字典加载日志模块配置
日志配置文件,setting_log.py
import logging # 定义日志文件的保存路径 logfile_path=r'D:\oldboyedu\manth-02\day-02\a1.log' # 定义日志格式 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' # 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' }, #打印到文件的日志, 'default': { 'level': 'DEBUG', 'class': 'logging.FileHandler', # 保存到文件 # logging.handlers.RotatingFileHandler 'formatter': 'standard', 'filename': logfile_path, # 日志文件 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了 }, }, 'loggers': { #logging.getLogger(__name__)拿到的logger配置 'logger1': { 'handlers': ['default', 'console'], 'level': 'DEBUG', 'propagate': False, }, }, }
升级修改的配置文件,增加日志轮转的功能
'default': { 'level': 'DEBUG', # 'class': 'logging.FileHandler', # 保存到文件 # logging.handlers.RotatingFileHandler 'class': 'logging.handlers.RotatingFileHandler', 'formatter': 'standard', 'filename': logfile_path, # 日志文件 'maxBytes': 1024*1024*5, # 日志文件大小 5M 'backupCount': 5, 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了 },
功能调用日志模块配置文件
import logging.config from setting_log import LOGGING_DIC # 导入日志的配置文件 logging.config.dictConfig(LOGGING_DIC) logging1 = logging.getLogger('logger1') logging1.debug('调试日志')
5)升级版,新增配置日志文件,如boss的日志
import logging # 定义日志文件的保存路径 logfile_path=r'D:\oldboyedu\manth-02\day-02\a1.log' boss_logfile_path=r'D:\oldboyedu\manth-02\day-02\a2.log' # 定义日志格式 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 = '[%(asctime)s] %(message)s' # 给boss的日志,简单明了的日志 # log配置字典 LOGGING_DIC = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': standard_format }, 'simple': { 'format': simple_format }, 'id_simple': { 'format': id_simple_format } }, 'filters': {}, 'handlers': { #打印到终端的日志 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 打印到终端 'formatter': 'simple' }, #打印到文件的日志, 'default': { 'level': 'DEBUG', 'class': 'logging.FileHandler', # 保存到文件 # logging.handlers.RotatingFileHandler 'formatter': 'standard', 'filename': logfile_path, # 日志文件 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了 }, # 打印给boss的日志 'boss': { 'level': 'ERROR', 'class': 'logging.FileHandler', # 保存到文件 # logging.handlers.RotatingFileHandler 'formatter': 'id_simple', 'filename': boss_logfile_path, # 日志文件 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了 }, }, 'loggers': { #logging.getLogger(__name__)拿到的logger配置 'logger1': { 'handlers': ['default', 'console','boss'], 'level': 'DEBUG', 'propagate': False, }, }, }
6)函数调用配置文件输出日志
def get_logger(logger_name): # 获取输入日志的信息 logging.config.dictConfig(settings.LOGGING_DIC) # 导入上面定义的settings配置 logger=logging.getLogger(logger_name) return logger logger=get_logger('logger1') def register(): logger.info('用户%s注册成功' %user) def info(): logger.info('用户%s登录成功' %user)
7)可实现任意log对象的配置,字典的key为空即可
'loggers': { #logging.getLogger(__name__)拿到的logger配置 '': { 'handlers': ['default', 'console'], 'level': 'DEBUG', 'propagate': False, }, },
8)扩展,log的日志格式
可在logging.basicConfig()函数中通过具体参数来更改logging模块默认行为,可用参数有 filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。 filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。 format:指定handler使用的日志显示格式。 datefmt:指定日期时间格式。 level:设置rootlogger(后边会讲解具体概念)的日志级别 stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。 #格式 %(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:用户输出的消息
9)引入其他模块的日志输出
import logging from logging.handlers import TimedRotatingFileHandler class LogConfig(object): #APP_LOG = '/opt/SRE/log/a.log' APP_LOG = './log/a.log' LOG_LEVEL = 'INFO' LOG_DATEFMT = '%Y-%m-%d %H:%M:%S' LOG_FORMAT = '[%(asctime)s] [%(process)d] [%(levelname)s] - %(module)s.%(funcName)s ' \ '(%(filename)s:%(lineno)d) - %(message)s' LOG_WHEN = 'D' LOG_INTERVAL = 1 LOG_ROTATE_BACKUP_COUNT = 30 class Logger(object): def __init__(self): self.log_format = logging.Formatter(LogConfig.LOG_FORMAT) self.logger = logging.getLogger() def init(self): self.set_handler() self.set_loglevel() def set_handler(self): level = logging.getLevelName(LogConfig.LOG_LEVEL) if LogConfig.APP_LOG == '': # No APP_LOG print colorful log to console pass # coloredlogs.install( # level=level, # fmt=LogConfig.LOG_FORMAT, # datefmt=LogConfig.LOG_DATEFMT, # ) else: file_handler = TimedRotatingFileHandler( filename=LogConfig.APP_LOG, when=LogConfig.LOG_WHEN, interval=LogConfig.LOG_INTERVAL, backupCount=LogConfig.LOG_ROTATE_BACKUP_COUNT, encoding='utf-8' ) file_handler.setFormatter(self.log_format) self.logger.addHandler(file_handler) # print to console # console_handler = logging.StreamHandler() # console_handler.setFormatter(self.log_format) # self.logger.addHandler(console_handler) def set_loglevel(self): log_level = LogConfig.LOG_LEVEL assert log_level in ['DEBUG', 'INFO', 'WARNING', 'ERROR'], "log level not correct" self.logger.setLevel(getattr(logging, log_level)) if __name__ == '__main__': loger = Logger() loger.init()
10)loguru模块的使用: pip3 install loguru
import os from loguru import logger dir_log = "logs" path_log = os.path.join(dir_log, '日志文件.log') logger.add(path_log, rotation='0:00', enqueue=True, serialize=False, encoding="utf-8", retention="10 days") logger.debug("服务器重启!")
参数意义
logger . add ( "file_1.log" , rotation = "500 MB" ) # 文件过大就会重新生成一个文件 logger . add ( "file_2.log" , rotation = "12:00" ) # 每天12点创建新文件 logger . add ( "file_3.log" , rotation = "1 week" ) # 文件时间过长就会创建新文件 logger . add ( "file_X.log" , retention = "10 days" ) # 一段时间后会清空 logger . add ( "file_Y.log" , compression = "zip" ) # 保存zip格式 logger . add ( "somefile.log" , enqueue = True ) # 异步写入 logger . add ( "somefile.log" , serialize = True ) # 序列化为json logger . add ( "file.log" , format = "{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}" ) 时间格式化
使用多文件处理
二、跨平台序列化存储数据。json和pickle
1)序列化的概念,意义
01 什么是序列化 序列化:把内存中的数据转成一种中间格式(json/pickle),然后存放到硬盘中,永久保存 反序列化:从文件中读出(json/pickle)格式,然后返解成python的数据类型 02 为什么要序列化 1、数据结构持久化 2、跨平台数据交互 03 如何进行序列化,反序列化 json: 缺点: 只能支持部分python的数据类型 优点: 所有的语言都支持json格式 应用: 如果需要考虑跨平台性,则需要用json格式 pickle 缺点: 只有python支持pickle格式 优点: pickle能够支持所有的python数据类型 应用: 如果不需要考虑跨平台性,则可以用pickle格式
2)json支持转换python格式的类型
3)json序列化模块的使用
import json # dic={'name':'egon','age':18,'is_beautiful':True} # #序列化 # res=json.dumps(dic) # 强调,json格式不识别单引号 # # print(res,type(res)) # with open('user.json','w',encoding='utf-8') as f: # f.write(res) # 反序列化 # with open('user.json','r',encoding='utf-8') as f: # res=f.read() # dic=json.loads(res) # print(dic['name']) # 强调,json格式不识别单引号 # with open('user1.json','r',encoding='utf-8') as f: # res=f.read() # # dic=json.loads(res) # print(dic['x']) # #序列化 # dic={'name':'egon','age':18,'is_beautiful':True} # # with open('user2.json','w',encoding='utf-8') as f: # json.dump(dic,f) # 反序列化 with open('user.json','r',encoding='utf-8') as f: dic=json.load(f) print(dic['name'])
4)pickle用法和json一模一样
import json import pickle # 序列化 # pickle可以序列化任意python的数据类型 # print(json.dumps({1,2,3})) # print(pickle.dumps({1,2,3})) #
上一篇: 4 位随机验证码 (JS)
下一篇: Java 学习笔记 - 方法重载
推荐阅读
-
模块编译成功,但 python 运行时找不到依赖项 名称为''的模块
-
Python 编程:常用模块分类组织
-
[代码与应用] 10 个最常用的 Python 软件包!
-
MySQL、PostgreSQL、ClickHouse、MongoDB 的区别,包含 5 个数据库的项目的适用场景 - I. 常用数据库概述
-
Blender Python] 5.Blender 场景中的集合 - 创建和添加新集合
-
4.4 章 python 中的循环结构必须相互嵌套:常用于形状(矩形、三角形、菱形)。
-
MATLAB 计算和建模的常用函数:5.曲线拟合
-
常用的5种机器学习模型类型概述
-
搞定!用Python3的numpy模块玩转argsort函数
-
用Python获取实时时间:time模块的妙用