21-补充模块知识:logging日志模块、json模块(序列化,反序列化)【进阶】

模块须知:

1、首次导入模块,发生三件事:1)创建一个模块的名称空间

                                                  2)执行模块对应的文件,将产生的名字存放在1)中的名称空间

                                                  3)在当前执行文件中拿到一个模块名,该模块名指向1)的名称空间

2、模块的查找顺序:1)内存中已经加载的模块

                                2)内置模块

                                3)sys.path路径中包含的模块   【注:sys.path的第一个路径为当前执行文件所在的文件夹】

一、logging模块  【日志模块】===》爬虫需要需要记录哪边错误,且不中断

【注:下面都是了解!!!其实日志只要把它写到一个模块,以后每次使用导入该模块即可!!!】

【So:定义一个mylogger.py  以后直接把它当成模块使用!!!】

调用:import logging

1、日志分为5个级别:

日志分类调用形式含义日志级别(用数字表示等级)
debuglogging.debug("debug......")调试信息10
infologging.info("info......")程序正常运行级别的信息20
warninglogging.warning("warning......")警告,可以忽略30
errorlogging.error("error......")错误40
criticallogging.critical("critical......")崩溃(严重)50

一般默认的日志级别为30,所以一般只打印:warning、error、critical

import logging
logging.debug('debug......')
logging.info('info......')
logging.warning('warning......')
logging.error('error......')
logging.critical('critical......')
"""
结果显示: #只打印warning、error、critical  【因为默认的日志级别为30】
WARNING:root:warning......
ERROR:root:error......
CRITICAL:root:critical......
"""  
#切默认输出结果为:日志级别:日志名:自己输入的信息

2、需求:针对默认的日志输入,需要建立一些新的设置

需求:(1)自己设置日志级别   (2)自己设置日志格式   (3)日志打印到屏幕(默认)且保存到文件(自己设置)

使用:logging.basicConfig(**kwargs)  进行日志参数的设置

参数:(1)filename:指定文件的路径用于存放日志

          (2)filemode:文件打开模式,可以为'a','w',默认是'a'

          (3)日志显示格式:一般情况下为:e569af0333e1c42aea89f7d1d3667dbeede.jpg

         (4)datafmt:日志时间格式

         (5)level:设置日志等级

         (6)stream:一半为sys.stdout,表示往屏幕输出

注意点:(1)filename和stream不能同时设置    【问题!!!需要考虑!!!】

             (2)logging.basicConfig(**kwargs)中没有设置编码encoding,日志文件默认编码是'gbk格式',但是pycharm使用'utf-8'编码

3、日志的小例子使用(自己设置logging.basicConfig(**kwargs)

import logging
logging.basicConfig(filename='access.log',format='%(asctime)s-%(name)s-%(levelname)s-%(module)s:%(message)s',datefmt='%Y-%m-%d %H:%M%S %p',level=10)
logging.debug('调试正常')
logging.info('正常运行')
logging.warning('警告')
logging.error('出错')
logging.critical('严重崩溃')

#此时出现文件夹:access.log,里面内容如下:

9ffb2010f688c888e5d5a9fcee2706bbc5b.jpg【但是要把编码设置为:‘gbk’,才可以查看】
4、logging模块中的四类对象  【自己敲一遍,知道关系即可】

四类对象:logger filter handler formatter

假设现在整个日志模块的布局为:c89cb80c0df570a3889d6839c8cd0043880.jpg

【建立日志:有两个输出到文件,有一个输出到屏幕;其中两个文件日志格式用formatter1,屏幕日志格式用formatter2】

(1)logger:负责生产日志

import logging
logger1=logging.getLogger('***')

注:***是日志的名称,自己设置

注:此时logger1有debug、info、warning、error、critical方法,可以用logger1产生日志

(2)filter:过滤日志(不常用)

(3)handler:控制日子打印到文件or终端

logging.Filehandler(filename,mode='a',encoding)  #打印到文件【可以自己指定编码,指定文utf-8】

logging.Streamhandler()  #打印到屏幕终端

fh1=logging.FileHandler('a1.log','a',encoding='utf-8')  #打印到文件
fh2=logging.FileHandler('a2.log','a',encoding='utf-8')  #打印到文件
sh=logging.StreamHandler()  #打印到屏幕

(4)formatter:控制日志的格式   logging.Formatter(fmt,datefmt)   其中fmt是日志格式,datefmt是日期格式

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')

根据上述日志布局c89cb80c0df570a3889d6839c8cd0043880.jpg,建立关系

#关系1:logger1把日志存储/显示到file1,file2和stream

【为logger对象绑定handler,利用addHandler()】

logger1.addHandler(fh1)
logger1.addHandler(fh2)
logger1.addHandler(sh)

#关系2:为handler绑定日志格式

【为logger对象绑定日志格式,利用setFormatter()】

fh1.setFormatter(formatter1)
fh2.setFormatter(formatter1)
sh.setFormatter(formatter2)

注:日志级别【涉及到两层关系】(第一层、第二层、第三层只是日志格式)

注:日志格式:两层关卡,必须都要通过,日志才能正常记录

logger1.setLevel(10)  #第一层
fh1.setLevel(10)   #第二层
fh2.setLevel(10)   #第二层
sh.setLevel(10)    #第二层

如此时:输入:logger1.debug('调试信息')

则:a1.log和a2.log文件formatter1格式:23e318b976d13c9b1fa90b789a635c48195.jpg30c36d9ec6f7374655822a981f088a0767d.jpg

    终端显示formatter2格式:260668c95cf339d365830274d1b1b5afc53.jpg

5、通过字典导入配置   【重点!!!这边的my_logging.py就是以后我需要导入的模块】

分为两块:(1)my_logging.py【日志配置文件,以后直接复制粘贴】===》当模块使用

                      (2)test.py  在其中导入my_logging.py文件,然后直接使用

【!!!这个流程就是以后的流程!!!】

(1)my_logging.py文件   【!!!以后直接把它当做模块导入!!!】

import logging
import logging.config

#定义三种日志格式的输出
standard_format = '[%(asctime)s][%(threadName)s:%(thread)s][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'

#定义日志文件的路径
LOG_PATH=r'access.log'

# log配置字典    ---->日后要是用的话,直接照着这个字典里面填写信息即可。 #重要的就是  'formatters':{}   'handlers':{}  'loggers':{}
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'  #终端打印格式:选择simple--->简洁
        },#打印到终端的日志
        'default': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',  #文件打印格式:选择standard--->规范
            'filename': LOG_PATH,  # 日志文件
            'maxBytes': 1024*1024*5,  # 日志大小 5M
            'backupCount': 5,#针对:若access_psy.log满了,则每5M就切分一个,会出现:access_psy.log1 access_psy.log2 ......access_psy.log5用于存放之前的日志【老日志】
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },#打印到文件的日志,收集info及以上的日志
    },    #控制日志写到:文件or终端  【所以有两种】
    'loggers': {
        #logging.getLogger(name)拿到的logger配置
        '': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': False,  # True-->向上(更高level的logger)传递。通常设置为False
        },  #注:''是日志名,可以自己修改,一般设置为空,自己调用的时候设置名称
    }#负责产生日志
}

def load_my_logging_cfg():  #加载日志的配置
    logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
    logger = logging.getLogger(__name__)  # 生成一个log实例,这里面的名字,自己设置
    logger.info('It works!')  # 记录该文件的运行状态

(2)test.py文件   在test.py文件中想调用这个设置好的log配置

import time
import logging
import my_logging  # 导入自定义的logging配置

logger = logging.getLogger('psy')  # 生成logger实例

def demo():
    logger.debug("start range... time:{}".format(time.time()))
    logger.info("中文测试开始。。。")
    for i in range(10):
        logger.debug("i:{}".format(i))
        time.sleep(0.2)
    else:
        logger.debug("over range... time:{}".format(time.time()))
    logger.info("中文测试结束。。。")

if __name__ == "__main__":
    my_logging.load_my_logging_cfg()  # 在你程序文件的入口加载自定义logging配置
    demo()

此时右键run test.py

文件access.log显示:dc4dc83f241c3d0736314d849ed44a31896.jpg

终端屏幕显示:3bec1f48857928ef71bc5d91538b70cff27.jpg

【注:这个要理解!!!!!!以后直接调用my_logging.py,把它当成模块导入即可!!!!】

二、json模块(序列化,反序列化)

序列化:内存中的数据结构====》转成一种中间格式====》存到文件中

反序列化:文件====》读取中间格式(字符串)====》eval转成内存中的数据格式

1、反序列化 

之前:eval()   就是去掉两边引号【单引号或双引号】

x='[1,2,3]'
print(eval(x))  #[1, 2, 3]

y="[1,2,3]"
print(eval(y))  #[1, 2, 3]

z="[1,true,false,null]"
print(eval(z))   #报错  因为:python中没有true,false,null

所以eval()反序列化有局限性,所以使用json()

现在反序列化:json.loads()

import json
x="[1,true,false,null]"
print(json.loads(x))   #[1, True, False, None]

2、序列化  json.dumps()

import json
dic={'name':'psy','age':18}
print(json.dumps(dic))  #{"age": 18, "name": "psy"}

注:json格式尽量是双引号

转载于:https://my.oschina.net/pansy0425/blog/3027230

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值