day12-内置模块学习(三)

我的博客呀,从以前的预习变成了复习了,复习的东西还没有写完,哎

今日目录

1.序列化模块

2.加密模块

3.包的使用

4.random模块

5.shutil模块

 

开始今日份总结

1.序列化模块

在学习序列化模块之前,对于网络传输以及文件写入读取都是采用将列表,字典这些数据类型转换成字符串进行,这样怎么说呢,能完成但是有点太low了,看一下以前的保存方式

dic = {'test':'test1与test2','test2':[1,2,3],'test3':{'a':'test','b':'test'}}
m1 = str(dic)
# with open('test','w',encoding='utf-8')as f1:
#     f1.write(m1)

with open('test','r',encoding='utf-8')as f2:
    ret  = f2.read()
    print(eval(ret))
#打印结果和dic的内容是一致的

不过在转换成可以使用的内容用的eval所以不建议使用,使用eval如果是黑客给的真实病毒,就会直接运行,有太大的风险,一般不使用。这就导入后面的序列化模块。

网络传输:转换成bytes,字节

文件写入:bytes,str

什么是序列化

序列化:将数据(数据结构)----->转换成特殊的字符串(用于网络传输)

反序列化:将网络传输或者是文件中特殊的字符串转换为原来的数据结构

以下是python中提供的序列化模块

  1.1 json模块

  json 序列化模块   是所有语言通用的一种标准(数据转化格式)。

  json可以转化的数据类型有

  # str int bool dict list(tuple)None  注意集合类型是没办法转换的

  json的用法就是俩对四个

  第一对方法:dumps与loads ,与网络传输有关

import json

dic ={'a':'bc','b':'cd','c':'ef'}
m1 = json.dumps(dic)#将dic转换成特殊的字符,这个时候就可以将m1写入文件
with open('test','w',encoding='utf-8')as f1:
    f1.write(m1)
# print(m1)
d1 = json.loads(m1)#将特殊的字符转换成原本格式
print(d1)#将转换后的字符串转换出来

  第二对方法:dump与load方法,与文件相关

dic ={'a':'bc','b':'cd','c':'ef'}
with open('test','w',encoding='utf-8')as f1:
    json.dump(dic,f1)
print('序列化成功!')#文件写入成功

with open('test','r',encoding='utf-8')as f2:   
    d1 = json.load(f2)
    print(d1)#文件读取成功

  补充方法:对于dump以及load方法每次只能读取或者写入一个对象,这个时候就有点尴尬了,这个时候就只能用第一对方法进行对多个对象进行操作了。

dic1 = {'name': '春哥'}
dic2 = {'name': '子伍'}
dic3 = {'name': '王子'}
dic4 = {'name': '女神'}
with open('test.json','w',encoding='utf-8') as f1:
    f1.write(json.dumps(dic1)+'\n')
    f1.write(json.dumps(dic2)+'\n')
    f1.write(json.dumps(dic3)+'\n')
    print('序列化成功!')
with open('test.json','a',encoding='utf-8')as f1:
    f1.write(json.dumps(dic4))
    print('yy')
with open('test.json','r',encoding='utf-8')as f2:
    for line in f2:
        print(json.loads(line))

json的参数

# s = json.dumps(dic,ensure_ascii=False,sort_keys=True,separators=('|',','))  # 序列化过程
# sort_keys 按键排序
# ensure_ascii=False 显示中文
# separators=('|',',') 设置分隔符 没有意义

总结:

  • loads与dumps是,对于网络传输,对于多个数据写入文件
  • load与dumpp是,只能用于单一数据结构写入文件
  • 如果字典的key为数字,在dumps和loads会将其转换为字符串

  1.2 pickle模块

  pickle与json一样是俩对四个用法

  dumps与loads 用于网络传输,将数据转换为bytes类型

dic1 = {'name': '春哥'}
dic2 = {'name': '子伍'}
dic3 = {'name': '王子'}
dic4 = {'name': '女神'}
import pickle
b1 = pickle.dumps(dic1)
print(b1)
m1 = pickle.loads(b1)
print(m1)

  dump与load 用于将多个数据写入文件,或者是读取

with open('test.pkl','wb')as f1:
    pickle.dump(dic1,f1)
    pickle.dump(dic2,f1)
    pickle.dump(dic3,f1)
    pickle.dump(dic4,f1)
with open('test.pkl','rb')as f2:
    ret = pickle.load(f2)
    ret1 = pickle.load(f2)
    ret2= pickle.load(f2)
    ret3= pickle.load(f2)
print(ret,ret1,ret2,ret3)

json与pickle的区别

  • json是多语言共用,通用性较好,适配str,int,dic,list,tuple,bool以及none
  • pickle是python自用的,可以转换python中的任何数据不过只能写成bytes类型

  1.3 shelve模块

  他也是python内置可以序列化的模块,不过他只能对文件进行操作

import shelve

f = shelve.open('shelve_file')
f['key'] ={'a':'bc','b':'de','c':'fg'}#直接对文件句柄操作,可以写入文件
f.close()
f = shelve.open('shelve_file')
print(f['key'])
f.close()

  shelve模块默认是不能对文件进行修改的,只能删除,增加,如果加入参数就可以修改了

f = shelve.open('shelve_file',writeback=True)#如果想要对shelve文件进行操作,必须设定writeback为真
f['key']['new_value'] ='the new message'
f.close()
f = shelve.open('shleve_file')
print(f['key'])
f.close()

2.加密模块

加密模块也加摘要算法,是一堆加密算法的集合体,一般的用法是给密码加密或者用作文件校验

hashlib:将str类型通过算法转换成一串等长度的数字

  • 不同的字符串,转换成数字肯定不同
  • 相同的字符串即使在不同的计算机上使用相同的加密方法,转换成的数字一定相同
  • hashlib加密不可逆,不能破解(如果破解一般都是加盐)

  2.1 MD5加密

   2.1.1 普通加密

import hashlib
#普通加密
ret = hashlib.md5()
ret.update('abc123'.encode('utf-8'))
print(ret.hexdigest())

ret.update('aaaaaaaaa'.encode('utf-8'))
print(ret.hexdigest())
#结果
e99a18c428cb38d5f260853678922e03
792b419cafa3cca8c85c497ff60910fd
#结果都是等长的字符串

   2.1.2 静态加盐加密

ret = hashlib.md5('我们来一场轰轰烈烈的测试'.encode('utf-8'))#这里就是加盐,对内容加固定的文件头
ret.update('abc123'.encode('utf-8'))
print(ret.hexdigest())

   2.1.3动态加盐加密

user_password = input('请输入你的密码>>>').strip()
ret= hashlib.md5(user_password[::-2].encode('utf-8'))#动态加盐将字符串切割,翻转取值
ret.update(user_password.encode('utf-8'))
print(ret.hexdigest())

   2.1.4 小文件校验

一般从网络上获取到文件,需要对他进行校验确定他是否传输的文件一致

def check_md5(file):
    ret = hashlib.md5()
    with open(file,mode ='rb')as f1:
        ret.update(f1.read())
        return ret.hexdigest()
print(check_md5('f1'))
print(check_md5('f2'))
#结果
b302efd21a6dc13ca8cdb584f1ce1613
b302efd21a6dc13ca8cdb584f1ce1613
#对于原文件如果将内容文字中间加空号或者其他都会变更,所以一般来确认文件的正确性

   2.1.5大文件校验

对于小文件,直接读取出来,这样可行,如果是大文件呢,一个文件上T这样不可能一次性读出来的,这个时候就需要另外的方式来做校验

在说明大文件加密之前有一个测试

#单独加密
ret = hashlib.md5()
ret.update('真相永远只有一个!'.encode('utf-8'))
print(ret.hexdigest())

#连续拼接加密
ret1 = hashlib.md5()
ret1.update('真相'.encode('utf-8'))
ret1.update('永远'.encode('utf-8'))
ret1.update('只有'.encode('utf-8'))
ret1.update('一个!'.encode('utf-8'))
print(ret1.hexdigest())
#结果
e269466c88819a19634e4ce95d1f12ae
e269466c88819a19634e4ce95d1f12ae

这说明将一个字符串分开,最后拼接在一起用相同加密的方式得到的结果是一致的。

def check_md5(file):
    ret = hashlib.md5()
    with open(file,mode='rb')as f1:
        while True:
            contect = f1.read(1024)#读取1024字节
            if contect:
                ret.update(contect)
            else:
                break
        return ret.hexdigest()
print(check_md5('f1'))
print(check_md5('f2'))
#结果
b302efd21a6dc13ca8cdb584f1ce1613
b302efd21a6dc13ca8cdb584f1ce1613

  2.2 sha加密

  sha的用法其实与md5的用法大同小异,都可以普通加密,带盐加密,动态盐加密,文件校验

ret= hashlib.sha1()#不同等级的sha
ret.update('123456'.encode('utf-8'))
print(ret.hexdigest())

ret1 = hashlib.sha256()#不同等级的sha
ret1.update('123456'.encode('utf-8'))
print(ret1.hexdigest())
#结果
7c4a8d09ca3762af61e59520943dc26494f8941b
8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92

就会发现不同等级的sha生成的密码长度完全不一致

sha与MD5的区别

  • MD5比较通用,加密效率快,安全性相对较差
  • sha系列,算法更好,安全性根据密码等级越高,效率低,耗时长

3.包的使用

  3.1 当函数过多了,可以分模块文件去管理函数,模块文件过多,需要将模块分类,放在一个一个的文件夹内。这个文件夹就叫做包,这样会使得组织结构更加清晰合理

当我们导入一个模块的时候会发生三件事

  1. 创建一个以模块命名的名称空间
  2. 执行模块代码,模块里面的代码会加载在模块名命名的名称空间的内存中
  3. 调用模块名的名字必须通过模块名的方式调用

包也是模块,他是模块的集合体,导入一个包也会发生三件事

  1. 创建一个以包的命名的名称空间
  2. 执行包内__iter__文件,将__iter__里面的代码块加载到包名对应的名称空间
  3. 调用包内的名字必须通过包名.的方式去调用

想要在此文件引用 bbb包的m3模块 怎么做?
第一步 在此文件 import aaa
第二步:在aaa 的 __init__ 添加 from aaa import bbb
第三步:在bbb 的 __init__ 添加 from aaa.bbb import m3
完成以上三步,那么我在此执行文件就可以引用bbb包的m3模块里面的名字。
aaa.bbb.m3.func3()

# 总结:
#  from a.b import c  .的左边一定是个包,import 后面一定一个具体的名字
# 包里面的__init__ 如果想要引用模块必须是 from ....import ... 不能直接 import
# from a.b.c.d import e.f.g  错误
# from a.b.c.d import e

  3.2 绝对导入与相对导入

绝对导入:以执行文件的sys.path为起点开始导入,称之为绝对导入

  • 优点:执行文件与被导入的模块都可以使用
  • 缺点:所有的导入都是以sys.path为起始点,导入麻烦

相对导入:参照当前所在文件的文件夹为起始开始查找,称之为相对导入

  • 符号:.代表当前所在文件的文件夹,..代表上一级文件夹,…代表上一级上一级的文件夹
  • 优点:导入更加简单
  • 缺点:只能在导入包中的模块才能使用

4.random模块

random就是一个随机模块

import random
print(random.random())#随机生成0到1内的小数
print(random.uniform(1,3))#随机生成1到3内的小数
print(random.randint(1,5))#随机生成大于等于1,小于等于5的整数
print(random.randrange(1,10,2))#随机生成1到10内的奇数
print(random.choice(['alex','wusir','日天']))#从列表中随机选出一个
print(random.sample(['alex','wusir','日天'],2))#从列表中随机选出多个
li =[1,2,3,4,5]
random.shuffle(li)#随机排列
print(li)

random的应用

#随机生成一个五字验证码
def get_code():
    code =''
    for i in range(5):
        num = str(random.randrange(10))#随机生成一个数字
        s = chr(random.randint(97,122))#随机生成一个小写字母
        s2 = chr(random.randint(65,90))#随机生成一个大写字母
        msg = random.choice([num,s,s2])#从数字,小写字母,大写字母中随机生成一个
        code+=msg
    print(code)

get_code()
#结果就一个五位随机验证码

5.shutil模块

import shutil

shutil.copyfileobj(open('f2','r'),open('f3','w'))#将f2的内容复制到f3
shutil.copyfile('f2','f2.bak')#将f2文件复制给bak文件
shutil.copytree('nb','nbb',ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))#复制一个文件夹

import time
import tarfile
# 打包文件
shutil.make_archive('NB1%s' %time.strftime('%Y-%m-%d'),'gztar',root_dir='NB1')


# 解压
t = tarfile.open('NB12019-01-10.tar.gz','r')
t.extractall('ttt')
t.close()
posted @ 2019-01-10 22:19  柴犬砍柴  阅读(181)  评论(0编辑  收藏  举报