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 侯冰雷 ~~欢迎转载 ~~欢迎关注 ~~欢迎留言
  • 相关阅读:
    Windows编程系列:Windows中的消息
    python 日志 logging模块
    wx-xcx
    大坑:perspectiveTransform
    在移动硬盘上装系统
    Django
    双边滤波(Bilateral filter)
    Mesh Deformation with Laplacian Coordinates
    C++五十一篇 -- VS2017开发人员新闻无法联网
    idea 修改Git密码和账号后,Git提交账号的没有改变
  • 原文地址:https://www.cnblogs.com/houbinglei/p/9300644.html
Copyright © 2011-2022 走看看