第五周:
Day 16
模块与包
1、什么是包
包是作为目录存在的,包的另外一个特点就是文件中有一个__init__.py
文件,如果我们忘记创建这个文件夹,就没法从这个文件夹里面导入那些模块。一句话来说包是一个含有__init__.py
文件的文件夹,本质就是一个模块,是用来被导入的
2、为何要有包
包的作用和模块的作用是相似的,因为很多功能没有自带,当我们需要使用这些功能的时候,可以通过下载标准库,第三方或者自定义一个拥有相同功能模块的含有__init__.py
文件文件夹,通过import
导入相关方法来完成自己的项目
3、包的使用
首次导入包这种模块主要做了两件事
1)创建模块的名称空间,运行包下的__init__.py
文件,将运行过程中产生的名称都丢入模块的名称空间中
实际上就是我们无法给包(文件夹)创建名称空间,所以用__init__
来代替给包创建
2)在当前位置拿到一个名字Package
,该名字指向__init__.py
的名称空间,即Package
名字,名字是来自于__init__.py
中的文件的名称空间,即Package
名称空间
当包与执行文件(run
)不在同级目录下时需要额外将包的路径添加到环境变量中(sys.path
)这一步是使用者来执行的,
那我们在创建了一个多级包目录的时候各级包的导入是怎么样的呢?
我们可以这样导入
3) run文件导包
from Package1.Package2.Package3 import Module31
Module31.m31()
4)下级文件导包逐级导入①从根目录向下导入
# ①Module 32
from Package1 import Module11
from Package1.Package2 import Module21
Module11.m11()
Module21.m21()
下级文件导包②相对导入只适用于包中的模块,顶层的模块中将不起作用(不能超过根目录)
from ... import Module11
from .. import Module21
Module11.m11()
Module21.m21()
#from ... import Module11
#ValueError: attempted relative import beyond top-level package
-
如果将
Run.py
当作顶层执行模块 -
- 2和 B将成为
**toplevel package
顶层包** 2中的模块不能用相对导入来导入B包中的模块,因为不能越过顶层包。 - 2、B 包中的目录可以导入本包中及以下的模块
- 2和 B将成为
2、json
\ pickle
模块
1、什么是序列化与反序列化
内存中某一类的数据---------------》特殊的格式
内存中某一类的数据《---------------特殊的格式
2、为何要序列化
1、存档:把内存中的数据持久化到硬盘
2、跨平台交互数据
在python中:
存档=》推荐用pickle格式
跨平台交互=》推荐用json格式
3、如何序列化
1、低级的序列化与反序列化方式
items=["圣剑","蝴蝶","BKB"]
dic_str=str(items)
with open('db.txt',mode='wt',encoding="utf-8") as f:
f.write(dic_str)
2.反序列化
with open('db.txt',mode='rt',encoding='utf-8') as f:
data=f.read() # "['圣剑', '蝴蝶', 'BKB']"
items=eval(data)
print(items[0])
2、用json来序列化
优点:跨平台交互数据
缺点:无法识别所有的python数据类型
注意:json格式的字符串里不能包含单引号
# 序列化方式一:
import json
t = {"a": 1, "b": 2} # 字典=======》json格式的字符串:"[1,2,3]"
res = json.dumps(t)
print(res, type(res))
with open("a.json", mode='wt', encoding='utf-8') as f:
f.write(res)
# json反序列化方式一:
with open("a.json", mode='rt', encoding='utf-8') as f:
data = f.read()
dic = json.loads(data)
print(dic, type(dic))
res = json.loads('{"k1":111}')
print(res['k1'])
# json序列化方式二:
t = {"a": 1, "b": 2} # 字典=======》json格式的字符串:"[1,2,3]"
with open("b.json", mode='wt', encoding='utf-8') as f:
json.dump(t, f)
# json反序列化方式二:
with open("b.json", mode='rt', encoding='utf-8') as f:
dic = json.load(f)
print(dic, type(dic))
注意:
load:针对文件句柄,将json格式的字符转换为dict,从文件中读取 (将string转换为dict)
with open("a.json", mode='rt', encoding='utf-8') as f:
dic = json.loads(f)
loads:针对内存对象,将string转换为dict (将string转换为dict)
a = json.loads('{'a':'1111','b':'2222'}')
2. dump 和 dumps(序列化)
dump:将dict类型转换为json字符串格式,写入到文件 (易存储)
with open("b.json", mode='wt', encoding='utf-8') as f:
json.dump(t, f)
dumps:将dict转换为string (易传输)
a_dict = {'a':'1111','b':'2222'}
a_str = json.dumps(a_dict)
3.pickle
优点:可以识别所有python类型
缺点:只能用于python中,无法跨平台交互pickle序列化后的数据,可读性差,人一般无法识别
1. pickle.dump(obj, file, [,protocol])
-
函数的功能:接受一个文件句柄和一个数据对象作为參数,把数据对象obj以特定的格式保存到给定的文件file里。
-
参数:
obj:想要序列化的obj对象。
file:文件名称。
protocol:序列化使用的协议。如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。
2.pickle.load(file)
函数的功能:将file中的对象序列化读出。
- 参数:
file:文件名称。
import pickle
s = {1, 2, 3, 4, 5}
res = pickle.dumps(s)
# print(res,type(res))
with open('a.pkl', mode='wb') as f:
f.write(res)
with open('a.pkl', mode='rb') as f:
data = f.read()
s = pickle.loads(data)
print(type(s))
3、hashlib模块
hash是一种算法(md5\sha256\sha512等),我们为该算法传入内容,该算法会计算得到一串hash值
hash值具备以下三个特点:
1、如果传入的内容一样,并且采用hash算法也一样,那么得到个hash值一定是一样的
2、hash值的长度取决于采用的算法,与传入的文本内容的大小无关
3、hash值不可逆
MD5
是最常见的摘要算法,速度很快,生成结果是固定的16字节,通常用一个32位的16进制字符串表示。SHA1算法更安全点,它的结果是20字节长度,通常用一个40位的16进制字符串表示。而比SHA1更安全的算法是SHA256和SHA512等等,不过越安全的算法越慢,并且摘要长度更长。
应用场景 :
密码加密
**(撞库)**很多用户喜欢用123456
,abcdef
,loveyou
这些简单的口令,由于MD5、SHA1等所有摘要算法都是公开的,黑客可以事先通过这些算法计算出这些常用口令的摘要值,得到一个反推表,然后,无需暴力破解,只需要对比数据库的密码摘要,就可以获得使用常用口令的用户账号。
“加盐”
额外给原始数据添加一点自定义的数据,使得生成的消息摘要不同于普通方式计算的摘要。
选取片段 做文件校验
下载文件的时候选取片段做哈希加密,与源文件片段的哈希值做对比,相同就是同一个文件。
import hashlib
m=hashlib.md5()
m.update("你好".encode('utf-8'))
m.update("egon".encode('utf-8'))
m.update("哈哈哈".encode('utf-8')) #"你好egon哈哈哈"
res=m.hexdigest()
print(res) # 824cb1b104e36de8f98ef38fbee759a5
加盐
pwd="123"
m3=hashlib.md5()
m3.update("天王盖地虎".encode('utf-8'))
m3.update(pwd.encode('utf-8'))
m3.update("小鸡炖蘑菇".encode('utf-8'))
print(m3.hexdigest())