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转成字符串
写到文件+\n

反序列化的时候
先按行读"{}\n"
去掉换行符之后使用loads反序列化

多个数据示例:

a = [1,2]
b = [1,2,3]
c = [1,2,3,4]

msg = ''
msg += json.dumps(a) + '\n'
msg += json.dumps(b) + '\n'
msg += '{}\n'.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模式覆盖
posted @ 2018-07-12 17:26  binglei  阅读(119)  评论(0编辑  收藏  举报