zoukankan      html  css  js  c++  java
  • day09_雷神_模块二

    day09

    序列化之json

    之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了,所以eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值。

    为什么要序列化?

    1:持久保存状态
    
    需知一个软件/程序的执行就在处理一系列状态的变化,在编程语言中,'状态'会以各种各样有结构的数据类型(也可简单的理解为变量)的形式被保存在内存中。
    
    内存是无法永久保存数据的,当程序运行了一段时间,我们断电或者重启程序,内存中关于这个程序的之前一段时间的数据(有结构)都被清空了。
    
    在断电或重启程序之前将程序当前内存中所有的数据都保存下来(保存到文件中),以便于下次程序执行能够从文件中载入之前的数据,然后继续执行,这就是序列化。
    
    具体的来说,你玩使命召唤闯到了第13关,你保存游戏状态,关机走人,下次再玩,还能从上次的位置开始继续闯关。或如,虚拟机状态的挂起等。
    
    2:跨平台数据交互
    
    序列化之后,不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,如果收发的双方约定好实用一种序列化的格式,那么便打破了平台/语言差异化带来的限制,实现了跨平台数据交互。
    
    反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
    

    序列化: 就是把内存里的数据结构保存下来。

    json格式字符串特点:

     json 只支持有限的数据类型 字典 列表 数字类型
     json 字典的key只能是字符串
     json引号只能是双引号
     python的None转换过来是null,也是字符串格式
    

    示例:

     1 import json
     2  
     3 dic={'name':'alvin','age':23,'sex':'male'}
     4 print(type(dic))#<class 'dict'>
     5  
     6 j=json.dumps(dic)
     7 print(type(j))#<class 'str'>
     8  
     9  
    10 f=open('序列化对象','w')
    11 f.write(j)  #-------------------等价于json.dump(dic,f)
    12 f.close()
    13 #-----------------------------反序列化<br>
    14 import json
    15 f=open('序列化对象')
    16 data=json.loads(f.read())#  等价于data=json.load(f)
    

    注意:

    import json
    #dct="{'1':111}"#json 不认单引号
    #dct=str({"1":111})#报错,因为生成的数据还是单引号:{'one': 1}
    
    dct='{"1":"111"}'
    print(json.loads(dct))
    
    #conclusion:
    #        无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads
    

    dumps多个数据

    需要连续dump,使用dumps
    10个字典
    分别对每一个字典进行dumps转成字符串
    写到文件+
    
    
    反序列化的时候
    先按行读"{}
    "
    去掉换行符之后使用loads反序列化
    

    多个数据示例:

    a = [1,2]
    b = [1,2,3]
    c = [1,2,3,4]
    
    msg = ''
    msg += json.dumps(a) + '
    '
    msg += json.dumps(b) + '
    '
    msg += '{}
    '.format(json.dumps(c))
    
    with open('a.json',mode='w') as f:
        f.write(msg)
    
    with open('a.json') as f:
        for i in f:
            obj = json.loads(i.strip())
            print(obj)
    

    序列化pickle

    优点:支持所有python数据类型;缺电:不能跨平台

    结果: pickle是bytes类型;json是字符串类型;
    

    pickle多个数据

    不能用for循环读取,是字节类型,json可以.strip() 去掉换行符,pickle不行;

    file = open('pickle_file','rb')
    while True:
        try:
            print(pickle.load(file))
        except EOFError:
            break
    

    示例:

     1 import pickle
     2  
     3 dic={'name':'alvin','age':23,'sex':'male'}
     4  
     5 print(type(dic))#<class 'dict'>
     6  
     7 j=pickle.dumps(dic)
     8 print(type(j))#<class 'bytes'>
     9  
    10  
    11 f=open('序列化对象_pickle','wb')#注意是w是写入str,wb是写入bytes,j是'bytes'
    12 f.write(j)  #-------------------等价于pickle.dump(dic,f)
    13  
    14 f.close()
    15 #-------------------------反序列化
    16 import pickle
    17 f=open('序列化对象_pickle','rb')
    18  
    19 data=pickle.loads(f.read())#  等价于data=pickle.load(f)
    20  
    21  
    22 print(data['age'])   
    

    日志 logging

    日志级别

    CRITICAL = 50 #FATAL = CRITICAL
    ERROR = 40
    WARNING = 30 #WARN = WARNING
    INFO = 20
    DEBUG = 10
    NOTSET = 0 #不设置
    
    默认级别为warning,默认打印到终端
    

    日志模块的四种角色

    1. logger对象: 产生日志
    2. filter对象: 日志过滤,几乎不用
    3. Handler对象:接收logger传过来的对象,进行日志格式化,可以打印到终端和文件。
    4. Formatter对象:日志格式
    

    设置日志级别

    handler可以设置(终端、文件)
    logger对象也可以设置,logger卡后边的级别。

    当前模块反射

    from conf import settings
    
    if hasattr(sys.modules[__name__],'settings'):
        print(getattr(sys.modules[__name__],'settings'))
    
    导入这个模块之后,就可以搜索到了。这是搜索当前导入的模块;
    看这个模块中有没有后边的'settings',是看在不在globals()的内容里;全局作用域里有没有。
    

    项目中的应用:

    """
    logging配置
    """
    
    import os
    import logging.config
    
    # 定义三种日志输出格式 开始
    
    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_dir = os.path.dirname(os.path.abspath(__file__))  # log文件的目录
    
    logfile_name = 'all2.log'  # log文件名
    
    # 如果不存在定义的日志目录就创建一个
    if not os.path.isdir(logfile_dir):
        os.mkdir(logfile_dir)
    
    # log文件的全路径
    logfile_path = os.path.join(logfile_dir, logfile_name)
    
    # 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)传递
            },
        },
    }
    
    
    def load_my_logging_cfg():
        logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
        logger = logging.getLogger(__name__)  # 生成一个log实例
        logger.info('It works!')  # 记录该文件的运行状态
    
    if __name__ == '__main__':
        load_my_logging_cfg()
    

    hashlib模块

    import hashlib
    def md5(name,pwd):
        hash_obj = hashlib.md5(name.encode('utf-8'))  # 加盐
        hash_obj.update(pwd.encode('utf-8'))  # 生成加密
        pwd = hash_obj.hexdigest()  # 打印加密,digest消化的意思
        return name,pwd
    
    ret = md5('alex','fdsa')
    print(ret)
    
    # 字符串是unicode编码,编码生成bytes类型。
    

    subprocess模块

    和os.system的区别:
    	把结果先存到一个地方,用的时候去取
    

    正确结果

    import subprocess
    import time
    obj=subprocess.Popen('tasklist',shell=True,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     )
    print(obj)
    print('第1次:',obj.stdout.read())
    # print('第2次:',obj.stdout.read())  第二次就没有东西了,因为第一次取完了
    print('---->主')
    
    print(obj.stdout.read().decode('gbk'))
    

    错误结果

    obj=subprocess.Popen('tssssasklist',shell=True,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     )
    
    print(obj.stdout.read())
    print(obj.stderr.read().decode('gbk'))
    

    一个程序的结果,丢给另外一个程序执行:

    obj1=subprocess.Popen('tasklist',shell=True,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     )
    
    obj2=subprocess.Popen('findstr python',shell=True,
                     stdin=obj1.stdout,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     )
    
    print(obj2.stdout.read())
    

    configparser 模块

    import configparser
    
    config=configparser.ConfigParser()
    config.read('my.ini') # 读到内存
    
    print(config.sections())
    print(config.options('mysqld'))  #  查看section是mysqld的配置项
    
    print(config.get('mysqld','charater-server-set'))  # 查看配置项是charater-server-set的值
    

    判断有没有配置项

    if config.has_option('mysqld','aaa'):
        print(config.get('mysqld','aaa'))
    

    正常get拿到的都是字符串类型

    print(config.getboolean('mysqld','skip-grant-table'))
    print(config.getint('mysqld','port'))
    print(config.getfloat('mysqld','port'))
    

    修改

    print(config.getboolean('mysqld','skip-grant-table'))
    print(config.getint('mysqld','port'))
    print(config.getfloat('mysqld','port'))
    
    
    config.add_section('egon')
    config.set('egon','name','egon')
    config.set('egon','age','18')
    
    config.set('client','password','alex3714')
    
    config.write(open('my.ini','w',encoding='utf-8')) # 在内存里对这个对象修改,这个对象已经是所有的值,所以只能是w模式覆盖
    My name is 侯冰雷 ~~欢迎转载 ~~欢迎关注 ~~欢迎留言
  • 相关阅读:
    HDU 2544 最短路
    HDU 3367 Pseudoforest
    USACO 2001 OPEN
    HDU 3371 Connect the Cities
    HDU 1301 Jungle Roads
    HDU 1879 继续畅通工程
    HDU 1233 还是畅通工程
    HDU 1162 Eddy's picture
    HDU 5745 La Vie en rose
    HDU 5744 Keep On Movin
  • 原文地址:https://www.cnblogs.com/houbinglei/p/9300644.html
Copyright © 2011-2022 走看看