疫情环境下的网络学习笔记 python 3.31

3.31

今日内容

  1. json & pickle模块

  2. shelve模块

  3. xml模块

  4. configparser模块

  5. hashlib模块

  6. suprocess模块

    运行系统命令,得到的结果不是字符,而是bytes类型

  7. logging模块

正课

序列化与反序列化

什么是序列化

序列化指的是把内存的数据类型转换成一个特定的格式的内容

序列化成的格式:json / pickle

原本我们学过序列化和反序列化的土办法:str() 与eval()

为何要序列化

序列化得到的特定格式有两种用途

  • 用于存储:可以存档
  • 传输给其他平台使用:跨平台数据交互,当一款软件的不同组建使用不同的编程语言编写的时候,不同语言的数据类型不兼容,如python中的列表与java中的数组

强调

  • 对用途1中的格式,可以是一种专用的格式:pickle只有python可以识别
  • 对于用途2中的特定格式,应该是一种通用,能够被所有语言识别的格式:json
  • json不能支持python所有的数据类型,json只是包含所有数据类型共有的类型:如集合就不在json中被支持

json

序列化:json.dumps

import json
res = json.dumps([1,'a',True])
print(res,type(res))

反序列化:json.loads

l = json.loads(res)
print(res)

读写文件序列化的简单方法

序列化写入文件的简单方法:json.dump(str,f)

with open('text.json',mode='rt',encoding='utf-8') as f:
	json.dump([1,'aaa',True,False],f)
    # 不用一行行字符串dumps再写,dump帮你写进去了

反序列化的简单方法 json.load(json,f)

with open('test.json',mode='rt',encoding='utf-8') as f:
    l=json.load(f)
    print(l,type(l))
    
# 不用一行行读了再反序列化,直接帮你读了
# 相当于
with open('test.json',mode='rt',encoding='utf-8') as f:
    json_res=f.read()
    l=json.loads(json_res)
    print(l,type(l))

json强调

  • json没有单引号,只用双引号

  • 一定要搞清楚json格式,不要跟python混淆

  • 在python2中,str就是bytes类型,python3.6以后,对于json格式前面加b,可以反解出正常的类型,只有3.5不行

    3.6可以用rb模式打开json格式文件,3.5只能用rt

猴子补丁

应用场景:想把原来的方法换成更好的办法,但是不想改变原本的使用模块的方法,也不想在程序的每一个文件里导入新的模块

把程序中的某种功能换掉,应该在入口文件打补丁,把要换掉的功能用新功能覆盖

import json
import ujson

def monkey_path_json():
	json.__name__='ujson'
	json.dumps = ujson.dumps
	json.loads = ujson.loads
    
# 把json的两个方法换成了ujson的两个方法,使用的时候名字不改变,在改变功能的时候名称空间不会改变,所以原来写的代码中json方法还是指向原来的
# 如果import ujson as json,因为产生了新的名称空间,后面调用的时候不会用ujson的名称空间

pickle

用法与json一样

XML

以前用的跨平台交互格式,用到就是xml,新的软件用的都是json

configparser

用于写配置文件,存放配置项

直接在目录里(db)建立文件,settings.ini,在db_handler里导入configparser就可以了

configparser专门用来解析如下的文件

[section1]
x=1
y=2
import configparser
config = configparser.ConfigParser()  # 这步得到一个对象,供我们操作
confi.read('test.ini')
# 获取所有的section,返回一个section名字的列表
print(config.sections())


# 获取某一section下所有的option的key
print(config.options('section1'))


# 获取某一个section下的所有key和value,返回小元组
print(config.items('section1'))

# 获取一个section下的一个value,得到的是字符串格式
print(config.get('section1','user'))

# 将读取的配置按指定类型输出
val1=config.getint('section1','age')  # int格式
val2=config.getboolean('section1','is_admin')  # 布尔值格式

hashlib 模块

hash一类算法接收传入的内容,经过运算得到一串hash值

hash值的特点

  • 只要每次传入的值一样,得到的结果一定一样

  • 如果固定一个hash算法,比如md5,无论传的内容有多大,其内容不会改变

  • 不能根据hash值反推到原内容:用于密码加密

    用户注册的时候不再传明文了,传hash值,登陆的时候也比较hash值

hash的用途

  • 用于密码密文传输与验证
  • 用于校验文件完整性,无论文件多大,得到的哈希值是固定的

如何用

import hashlib
# 使用md5,使用别的方法也是得到哈希值,复杂度不同,得到的长度不一样
m = hashib.md5('hello'.encode('utf-8'))
# m相当于一个哈希工厂,用update往里面送原料,最终得到的结果是所有传入的值拼接起来哈希的结果
m.update('hello'.encode('utf-8'))
m.update('world'.encode('utf-8'))

res = m.hexdigest()  # 拿到 'hellohelloworld' 的哈希值 

校验的时候,推荐使用for循环一行行m.update(line)方法,缺点是行数多的时候会比较慢

改进:

# 随机地取某一段进行校验
f = open('a.txt','rb')
f.seek(随机数)  # 随机选几个位置
info = f.read(2000)  # 一次读2000个字节
m1.update(info)

这样在保证大概率文件完整的情况下,提高了hash校验的速度

模拟撞库

import hashlib
passwords = ['111','222','ssss']
dic = {}
# 制作密码字典
for p in passwords:
	res = hashlib.md5(p.encode('utf-8'))
	dic[p] = res.hexdigest()

# 撞库
for k,v in dic.items():
	if v == cryptograph:
		print('撞库成功,名文密码是 %s' %k)
		break

提升撞库的成本

密码加盐

import hashlib
m = hashlib.md5()
m.update('nb'.encode('utf-8'))
m.update('deimos'.encode('utf-8'))
m.update('nb'.encode('utf-8'))
print(m.hexdigest)
# 拿到密码之后先对明文进行处理,对某些位置拆开,加入干扰的字符

为密码加盐,撞库就必须连同密码和盐一起猜,撞库成功后也没有这么容易把盐和原密码分隔开

subprocess

用于执行系统命令的模块,得到的结果都是bytes类型,不会乱码

import subprocess
subprocess.Popen()

猜你喜欢

转载自www.cnblogs.com/telecasterfanclub/p/12607425.html
今日推荐