模块

一.在python中使用正则表达式

1.转义符

(1)在python中的转义符

print(r"C\next")     在python中r是取消所有转义

(2)在正则表达式中的转义符

"("   表示匹配小括号   转义  (还是当括号来使用

[() + * ? / $ . ]    在字符组中这些字符会现出原形  还是当他们本身来使用

所有的w,d,s( , ),W,D,S 都是表示它原本的意义 

[-]只有写在字符组的首位的时候表示普通的减号

  写在其他位置上表示范围:[1-9]

  如果就是想要匹配减号:[1-9]


二.re模块

1.字符串

(1)匹配

  findall*****(正则表达式,参数)    返回值类型:列表形式    返回值的个数:1(一个列表)    返回值的内容:所有匹配上的项

例如:

import re
ret = re.findall("d+","342dssf234")
print(ret) ====>['342', '234']

例如:没有匹配上

import re
ret = re.findall("s+","342dssf234")
print(ret) =====>[]

  search*****(正则表达式,参数)    返回值类型:正则表达式匹配给的对象,需要通过group来获取匹配到的第一个结果,类型是字符串      返回值的个数为:1     返回值的内容:为第一个匹配到的值    

例如:

import re
ret = re.search("d+","223dsf33")
print(ret.group()) ====>223

例如:没有匹配结果返回None

import re
ret = re.search("s+","223dsf33")
print(ret) =====>None

  match(正则表达式,参数)    和search基本相同

区别:

例如:

import re
ret = re.match("d+","$232sdfd")
print(ret.group()) ====>会直接报错


import re
ret = re.search("d+","$^223dsf33")
print(ret.group()) ====>223 不会报错,不会受到影响

(2)替换

  sub(正则表达式,要替换的内容,参数)

例如:

import re
ret = re.sub("d+","A","12sfd232sfsf23")
print(ret) ====>AsfdAsfsfA

例如:替换的次数

import re
ret = re.sub("d+","A","12sfd232sfsf23",2)
print(ret) ====>AsfdAsfsf23

  subn(正则表达式,替换的内容,参数)     打印出来的数据类型是个元组   第二位是替换的次数

例如:

import re
ret = re.subn("d+","A","12sfd232sfsf23")
print(ret) ====>('AsfdAsfsfA', 3)

(3)切割

  split(正则表达式,参数)       打印出来的数据类型是列表     是以正则表达式进行切割

例如:

import re
ret = re.split("d+","alex23egon34taibai40")
print(ret) =====>['alex', 'egon', 'taibai', '']

(4)进阶方法    ----(主要用于爬虫和自动化开发)

  compile (是将正则表达式编译成为一个正则表达式的对象)   首先将正则表达式转义,转义成python解释器可以理解的代码,然后再执行代码

(提高时间效率)

例如:

import re
ret = re.compile("-0.d+|-[1-9]+(.d+)?")
res = ret.search("alex-23sdlds-56sdfsg23")
print(res.group()) =====>-23

(只有在多次使用某一个相同的正则表达式的时候,这个compile才会帮助我们提高程序的效率)

  finditer(finditer返回的是一个存放匹配结果的迭代器)

(提高空间效率)`

例如:

import re
ret = re.finditer("d+","ds3sy4784a235")
print(ret) =====> <callable_iterator object at 0x00000218E531FB38>
print(next(ret).group()) ====> 3 查看第一个结果
print(next(ret).group()) ====> 4784 查看第二个结果
print([i.group() for i in ret]) ===> ['235'] 查看剩余的结果

例如: 拿到全部的在值

import re
ret = re.finditer("d+","ds3sy4784a235")
for i in ret:
print(i.group()) ====>循环遍历 3 4784 235

2.优先级查询

(1)findall的优先级查询              (?:正则表达式)取消分组优先

例如:

import re
ret = re.findall("www.baodu.com|www.oldboy.com","www.oldboy.com")
print(ret) =====>['www.oldboy.com']

例如:

import re
ret = re.findall("www.(?:baidu|oldboy).com","www.oldboy.com")
print(ret) =====>['www.oldboy.com']

例如:

import re
ret = re.findall("www.(baidu|oldboy).com","www.oldboy.com")
print(ret) ====>['oldboy'] 在这里因为findall会优先匹配结果组里的内容返回,如果想要匹配结果,取消权限就可以在括号里面前面添加?:

(2)split的优先级查询    (遇到分组,会保留分组内被切割掉的内容)

例如:

import re
ret = re.split("(d+)","alex24egon34taibai40")
print(ret) =====>['alex', '24', 'egon', '34', 'taibai', '40', '']

(3)search  (如果search中有分组的话,通过group(n)能够拿到group中的匹配内容)

例如:

import re
ret = re.search("d+(.d+)(.d+)(.d+)?","1.2.3.4-2")
print(ret.group(3)) =====>.4
print(ret.group(2)) =====>.3
print(ret.group()) =====>1.2.3.4

分组的例子

1.只取参数中的整数

import re
ret = re.findall("d+(?:.d+)|(d+)","1-2*(60+(-40.35/5)-(-4*3)")
print(ret) =====>['1', '2', '60', '', '5', '4', '3']
ret.remove("")
print(ret) =====>['1', '2', '60', '5', '4', '3']

2.分别取出<a>wahaha</a> 中的 a  wahaha   /a

import re
ret = re.search(r"<w+>(w+)<(/w+)>",r"<a>wahaha</a>")
print(ret.group()) =====> <a>wahaha</a>
print(ret.group(1)) =====> wahaha
print(ret.group(2)) =====> /a

 

3.分组命名  

(1)?P<name>  分组命名的语法    name为组名

import re
ret = re.search("<(?P<name>w+)>w+</(?P=name)>","<h1>qqxing</h1>")
print(ret.group()) =====> <h1>qqxing</h1>
print(ret.group("name")) =====> h1 可以在group里面填写组名,找到该组名对应的值

(2)如果不给组起名字,也可以用序号来找到对应的组,表示要找的内容和前面的组的内容一致

import re
ret = re.search(r"<(w+)>w+</1>","<a>wahaha</a>")
print(ret.group()) =====> <a>wahaha</a>
import re
ret = re.search(r"<(w+)>(w+)</2>","<a>wahaha</wahaha>")
print(ret.group()) ======> <a>wahaha</wahaha>

(3)分组命名

分组命名

  (?P<name>正则表达式)    表示给分组起名字

  (?P=name)   表示使用这个分组,这里匹配到的内容应该和分组中的内容完全相同

通过索引使用分组

  1表示使用第一组,匹配到的内容必须和第一个组中的内容完全相同


三.random模块   (随机:在某个范围内取到每一个值的概率是相同的)

import random

1.随机小数

(1)0-1之间的随机小数

  print(random.random(1))

(2)任意之间的随机小数

  print(random.uniform(1,5))      (1,5之间的随机小数)

  无限循环小数   包含在float里

2.随机整数

(1)[1,2]包含2在内的范围的随机整数

  print(random.randint(1,2))

(2)[1,2)不包含2在内的范围的随机整数

  print(random.randrange(1,2))

(3)[1,10)不包含10在内的范围内的随机奇数

  print(random.randrange(1,10,2))

3.随机抽取

(1)随机抽取一个值

  lst = [1,2,3,"aaa",("wahaha","qqxing")]

  ret = random.choice(lst)

  print(ret)          

(2)随机抽取多个值

  lst = [1,2,3,"aaa",("wahaha","qqxing")]

  ret = random.sampe(lst)

  print(ret)     

4.打乱顺序    (在原列表中的基础上做乱序)  只能排列表

    lst = [1,2,3,"aaa",("wahaha","qqxing")] 

  random.shuffle(lst)

  print(lst)


四.时间模块  time

1.时间戳时间     (格林威治时间,float数据类型)        是给机器看的时间

  1970.1.1 0:0:0   (英国伦敦的时间)

  1970.1.1 8:0:0   (北京时间)

import time
print(time.time()) =====> 1533714658.3928015

2.结构化时间     (时间对象:能够通过.属性名来获取对象中的值)          从给机器看的 ------>给人看的过程

时间元祖:

import time
time_obj = time.localtime() 对象数据结构
print(time_obj) =====>time.struct_time(tm_year=2018, tm_mon=8, tm_mday=8, tm_hour=15, tm_min=48, tm_sec=9, tm_wday=2, tm_yday=220, tm_isdst=0)
print(time_obj.tm_year) =====>2018

3.格式化时间     (可以根据你的需要的格式来显示时间)        给人看的时间

时间字符串:

import time
print(time.strftime("%Y-%m-%d %H:%M:%S")) =====>2018-08-08 15:52:49
print(time.strftime("%Y/%m/%d %H-%M-%S"))      =====>2018/08/08 15-53-52

4.三种格式之间的转换

 

(1)由时间戳时间 ----->格式化时间

import time
time_obj = time.localtime(1500000000) ======> (时间戳时间(time.time()))
ret = time.strftime("%Y-%m-%d",time_obj) ======> ("格式定义","结构化时间")
print(ret) =====> 2017-07-14

 (2)格式化时间 ------>时间戳时间

import time
ret = time.strptime("2018-08-08","%Y-%m-%d") =======>("时间字符串","该时间对应的格式")
time_obj = time.mktime(ret)
print(time_obj) =====> 1533657600.0

 练习题: 求本月一号的时间戳时间

(1)方法一:

import time
ret = time.localtime()
ret = time.strptime("%s-%s-1" % (ret.tm_year,ret.tm_mon),"%Y-%m-%d")
a = time.mktime(ret)
print(a)

(2)方法二

import time
ret = time.strftime("%Y-%m-1")
a = time.strptime(ret,"%Y-%m-%d")
b = time.mktime(a)
print(b)


五.sys模块

sys模块是与python解释器交互的一个接口

1.sys.path

返回模块的搜索路径,初始化使用python.path环境变量的值

2.sys.modules

表示所有在当前python程序中导入的模块的内存地址

3.sys.platform

返回操作系统平台的名称    win32/win64   但是在pycharm中不准确

4.sys.exit()

退出程序  正常退出是sys.exit(1)   错误退出是sys.exit(0)

5.sys.argv

(1)打印出来的是列表数据类型

(2)第一个元素是执行这个文件的相对路径,也就是写在python命令后面的第一个值

(3)python命令后面的值都可以打印出来,之后的元素,在执行python启动的时候可以写多个值,都会依次添加到列表中

有什么用?怎么用?   (在cmd练习中操作)

import sys
name = sys.argv[1]
psw = sys.argv[2]
if name == "alex" and psw == "123":
print("执行以下代码")
else:
exit()


六.os模块

 os模块是与操作系统交互的一个接口

(1)os.getcwd() 

在哪个地方执行了这个文件,getcwd的结果就是执行的那个文件所在文件夹的绝对路径

import os
print(os.getcwd())

 

(2)os.chdir()

import os
print(os.getcwd())
os.chdir(r"E:python作业Python面向对象")
print(os.getcwd())

(3)os.mkdir("文件夹名字")       创建一个文件夹

import os
os.mkdir('dir1')

import os
os.mkdir('dir1/dir2') (如果dir1存在,就会在dir1下面在创建一个dir2,并不会报错,这也相当于创建一个文件夹)

(4)os.makedir("dir2/dir3/dir4")     创建多层递归目录

import os
os.makedirs("dir2/dir3/dir4")

 

如果已经存在文件,也不会报错,如果没有,就新建

import os
os.makedirs("dir2/dir3/dir4",exist_ok=True)
os.makedirs("dir2/dir3/dir5",exist_ok=True)

 

 (5)os.rmdir("dir2/dir3/dir4")     删除一个文件夹(但是不能删除非空文件夹)

import os
os.rmdir("dir2/dir3/dir4") ===.dir4 被删除了

import os
os.remove("dir2/dir3/dir5/aa")
os.rmdir("dir2/dir3/dir5")

 (6)os.removedirs("dir2/dir3/dir4")      

  递归向上删除文件,只要删除当前目录之后,发现上一级目录也为空,就把上一级目录删除,如果上一层目录里有其它文件,就停止删除

import os
os.removedirs("dir2/dir3/dir4")

(7)os.remove("文件绝对路径")   删除文件

import os
os.remove("dir1/dir2/aaa")

 

(8)os.rename("旧名字","新名字")     重命名 

import os
os.rename("dir1/aaa","dir1/bbb")

 

(9)os.listdir("路径")      可以查看该路径下的全部文件夹

import os
print(os.listdir(r"E:python作业"))

(10)os.stat("路径")     查看文件的状态

import os
print(os.stat(r"E:python作业Python面向对象20180808dir1bb"))

 

(11)os.sep("路径")     当前你所在的操作系统的目录的分隔符

import os
print(os.sep)

  win 下为"\"      Linux下为""

(12)os.linesep()     输入当前平台使用的行终止符

import os
print([os.linesep])

   win下为[" "]     Linux下为[" "]

(13)os.pathsep      输出用于分割文件路径的字符串

import os
print(os.pathsep)

   win下为";"        Linux下为":"

(14)os.name          输出字符串指示当前使用平台

import os
print(os.name)

  win下为"nt"     Linux下为"posix"

(15)os.system("命令")        用于删除文件/copy一个文件的时候使用(不关心结果)     用于自动化开发

import os 
print(os.system("ipconfig"))

(16)os.popen("文件名")        用于查看当前路径,查看某些信息的时候使用      用于自动化开发

import os
ret = os.popen("ipconfig")
print(ret.read())

(17)os.environ    能够打开操作系统/python系统环境变量

import os
print(os.environ)

os.path

(18)os.path.abspath("路径")      返回规范过的绝对路径

import os
ret = os.path.abspath(r"E:python作业Python面向对象\20180808练习.py")
print(ret)

 

(19)os.path.split("路径")      将路径切割成目录和文件名的元组

import os
ret = os.path.split(r"E:python作业Python面向对象20180808练习.py")
print(ret)

(20)os.path.dirname("路径")     返回的是os.path.split("路径")切割后的第一个元素

import os
ret = os.path.dirname(r"E:python作业Python面向对象20180808练习.py")
print(ret)

 

(21)os.path.basename("路径")     返回的是路径最后的文件名,如果路径是以""或者"/"结尾的,返回的结果就会为空

import os
ret = os.path.basename(r"E:python作业Python面向对象20180808练习.py")
print(ret)

 

import os
ret = os.path.basename(r"E:python作业Python面向对象20180808/")
print(ret)


(22)os.path.exists("路径")        查看该路径是否存在,如果该路径存在返回True   如果不存在就返回False

import os
ret = os.path.exists(r"E:python作业Python面向对象20180808练习.py")
print(ret)

(23)os.path.isabs("路径")      如果是绝对路径,返回True

import os
ret = os.path.isabs(r"E:python作业Python面向对象20180808练习.py")
print(ret)

绝对路径:(E:python作业Python面向对象20180808练习.py)

相对路径:(练习.py)

(24)os.path.isfile("路径")    如果路径是一个存在的文件,就返回True,否则返回False

import os
ret = os.path.isfile(r"E:python作业Python面向对象20180808练习.py")
print(ret)

(25)os.path.isdir("路径")    如果路径是一个存在文件夹或者目录,就返回True,否则返回False

import os
ret = os.path.isdir(r"E:python作业Python面向对象20180808")
print(ret)

 (26)os.path.join(path1[,path2[,......]])   将多个路径组合后返回,第一个绝对路径之前的参数将被忽略

(27)os.path.getatime("路径")    返回路径指向的文件/目录/文件夹最后访问的时间

import os
ret = os.path.getatime(r"E:python作业Python面向对象20180808练习.py")
print(ret) =====>打印出来的是时间戳时间的flost的数据类型

 

(28)os.path.getmtime("路径")      返回路径指向的文件/目录/文件夹最后修改的时间

import os
ret = os.path.getmtime(r"E:python作业Python面向对象20180808练习.py")
print(ret)

 

(29)os.path.getsize("路径")        返回文件/文件夹/目录的大小    (文件夹/目录的大小始终是4096)

import os
ret = os.path.getsize(r"E:python作业Python面向对象20180808练习.py")
print(ret)


七.序列化模块

 序列化:将原本的字典,列表等内容换成一个字符串的过程就叫序列化

 1.序列化的目的:

(1)以某种存储形式使自定义对象持久化

(2)将对象从一个地方传递到另一个地方

(3)使程序更具维护性

2.为什么要序列化?

(1)要把内容写进文件

(2)网络传输数据

 

3.模块

(1) json模块   *****

① json的功能:

   dumps 功能     可以处理嵌套型的数据类型

import json
l = [1,{"aaa":123,"bbb":456},3,{"ABC":"678"}]
str_l = json.dumps(l)
print(str_l,type(str_l))

 

   loads 功能    反序列化:将一个字符串格式的数据类型换成他原本的类型   

import json
l = [1,{"aaa":123,"bbb":456},3,{"ABC":"678"}]
str_l = json.dumps(l)
ll = json.loads(str_l)
print(ll)

 

   dump 功能       接收一个文件句柄,直接将字典转换成json字符串写入文件

mport json
f = open("json_file",mode="w",encoding="utf-8")
dic = {"aaa":123,"bbb":456}
json.dump(dic,f)
f.close

 

   load   功能     load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回

mport json
f = open("json_file")
dic1 = json.load(f)
f.close()
print(dic1,type(dic1))

 

② json模块的补充

json模块格式的key必须是字符串数据类型

json格式中的字符串只能是" "

set集合不能dump/dumps

  如果是数字key,那么dumps之后会强行转换成字符串数据类型

import json
dic = {123:456,678:234}
str_dic = json.dumps(dic)
print(str_dic) ======> {"123": 456, "678": 234}

new_dic = json.loads(str_dic)
print(new_dic) ======> {'123': 456, '678': 234}

  json是否支持元组,当元组做value的字典会把 元组强制转换成列表

import json
dic = {"abc":(4,5,6)}
str_dic = json.dumps(dic)
print(str_dic) =======> {"abc": [4, 5, 6]}

new_dic = json.loads(str_dic)
print(new_dic) =======> {'abc': [4, 5, 6]}

  json不支持元组做keyimport json

dic = {(1,2,3):"abd"}
str_dic = json.dumps(dic)
print(str_dic)
=======> 直接报错

  对列表dump  (如果dump完之后,自己强行把文件中的" ",改成' ',则在load的时候就会报错)

import json
lst = ["aaa","bbb","ccc"]
with open("json_dump","w")as f:
json.dump(lst,f) ======> ["aaa", "bbb", "ccc"]
with open("json_dump")as f:
ret = json.load(f)
print(ret) ======> ['aaa', 'bbb', 'ccc']

  json可以多次dump数据到文件里,但是不能load出来

import json
lst = ["aaa","bbb","ccc"]
dic = {"abc":(4,5,6)}
with open("json_dump","w")as f:
json.dump(lst,f)
json.dump(dic,f) =======>["aaa", "bbb", "ccc"]{"abc": [4, 5, 6]}

with open("json_dump")as f:
ret = json.load(f)
print(ret) =======> 直接报错

  想dump多个数据的时候,就用dumps

import json
lst = ["aaa","bbb","ccc"]
dic = {"abc":(4,5,6)}
with open("json_dump","w")as f:
str_lst = json.dumps(lst)
str_dic = json.dumps(dic)
f.write(str_lst+" ")
f.write(str_dic+" ") =======>["aaa", "bbb", "ccc"]
                            {"abc": [4, 5, 6]}
with open("json_dump")as f:
for line in f:
ret = json.loads(line)
print(ret) =====>['aaa', 'bbb', 'ccc']
                             {'abc': [4, 5, 6]}

  json也可以转中文格式的

import json
dic = {"abc":123,"country":"中国"}
str_dic = json.dumps(dic,ensure_ascii=False)
print(str_dic) ========>{"abc": 123, "country": "中国"}

new_dic = json.loads(str_dic)
print(new_dic) ========>{'abc': 123, 'country': '中国'}

  文件中也可以转中文格式

import json
dic = {"abc":123,"country":"中国"}
with open("json_dump","w",encoding="utf-8")as f:
json.dump(dic,f,ensure_ascii=False) =====> {"abc": 123, "country": "中国"}
with open("json_dump","r",encoding="utf-8")as f:
ret = json.load(f)
print(ret) =====> {'abc': 123, 'country': '中国'}

  json的其他参数,是为了用户看的更方便,但是会相对浪费存储空间

import json
data = {"username" : ["李华","二愣子"],"sex":"男","age":16}
json_dic = json.dumps(data,sort_keys=True,indent=4,separators=(",",":"),ensure_ascii=False)
print(json_dic)
=======>
          {
          "age":16,
          "sex":"男",
          "username":[
            "李华",
            "二愣子"
            ]
          }

sort_keys = True :字典key的首字母按照英文排序

indent: 设置缩进

separators = (",")     按照 , 进行分割

(2) pickle模块   *****

pickle模块适合用于保存状态和对象

pickle模块dump/dumps的结果是bytes类型,dump用的f文件句柄的时候需要以"wb"的形式打开,load则用的是"rb"形式

pickle模块支持几乎所有对象的序列化

① pickle模块dump/dumps出来的结果是bytes类型

import pickle
dic = {1:(1,2,3),("a","b"):4}
pic_dic = pickle.dumps(dic)
print(pic_dic) ======> b'x80x03}qx00(Kx01Kx01Kx02Kx03x87qx01Xx01x00x00x00aqx02Xx01x00x00x00bqx03x86qx04Kx04u.'

new_dic = pickle.loads(pic_dic)
print(new_dic) ======> {1: (1, 2, 3), ('a', 'b'): 4}

② pickle模块能够处理够复杂的数据类型,会原封不动的恢复到原来的状态

import pickle
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
alex = Student("alex",45)
ret = pickle.dumps(alex) 可以把类中的实例化自定义的对象也dumps
print(ret) ======> b'x80x03c__main__ Student qx00)x81qx01}qx02(Xx04x00x00x00nameqx03Xx04x00x00x00alexqx04Xx03x00x00x00ageqx05K-ub.'

小花 = pickle.loads(ret)
print(小花.name) ======> alex
print(小花.age) ======> 45

③ dump用文件句柄的时候需要用"wb"打开,load用文件句柄的时候需要以"rb"模式

import pickle
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
alex = Student("alex",45)
with open("pickle_dump","wb")as f:
pickle.dump(alex,f)

with open("pickle_dump","rb")as f:
ret = pickle.load(f)
print(ret.name,ret.age)

④ 对于多次dump/load的操作做了良好的处理

import pickle
with open("pickle_dump","wb")as f:
pickle.dump({"k1":"v1"},f)
pickle.dump({"123":"456"},f)
pickle.dump({"abc":"def"},f)

with open("pickle_dump","rb")as f:
while True:
try:
print(pickle.load(f))
except EOFError:
break

(3) shelve 模块 

如果你写一定了一个文件(改动比较少),读文件操作比较多,且你大部分的读取都需要基于某个key获取某个value值

import shelve
f = shelve.open("shelve_demo")
f["key"] = {"k1":(1,2,3),"k2":"v2"}
f.close() =====>关闭文件

f = shelve.open("shelve_demo") ====>open打开文件就是在占用文件
content = f["key"]
f.close()
print(content) =====> {'k1': (1, 2, 3), 'k2': 'v2'}

八.hashlib模块  (摘要算法的模块)

import hashlib 

1.hashlib模块的第一个用法是:登录的密文验证

hashlib模块能够把一个字符串类型的变量转换成一个定长的密文的字符串,字符串里的每一个字符都是十六进制的数字

它能够将字符串转换成密文,但是密文没有办法转回为字符串

算法:对于同一个字符串,用相同的算法,相同的手段去进行摘要,获得的值总是相同的

(1).md5算法  (32位的字符串,每一个字符都是一个十六进制)

例如:

import hashlib

s = "alex"
md5_obj = hashlib.md5() #先实例化一个对象
md5_obj.update(s.encode("utf-8")) #update里必须写的是bytes类型
res = md5_obj.hexdigest() #对字符串进行摘要加密
print(res,len(res),type(res))

md5 的优缺点:

 (1)计算速度快,没有sha()算法复杂

 (2)md5()普及

 (3)算法相对简单

 (4)md5由于使用的人太多,撞库的几率比较高,所以不够安全

(2).sha()算法  (40位的字符串,每一个字符都是十六进制)

例如:

import hashlib

s = "alex"
m = hashlib.sha1() #实例化一个sha对象
m.update(s.encode("utf-8"))
res = m.hexdigest()
print(res,len(res),type(res))

 

sha1的优缺点:

(1)算法相对复杂

(2)计算速度慢

(3)用的人少,所以安全性相对比较高

md5,sha1具有相同的特点:

对于同一个字符串,不管这个字符串有多长,只要是相同的,无论在任何环境下,多少次执行,在任何语言中,使用相同的算法/相同的手段得到的结果永远是相同的

只要不是相同的字符串得到的结果一定不同

(3).md5/sha1加盐

例如:

import hashlib

s = "alex"
md5_obj = hashlib.md5("wusir".encode("utf-8")) #在这个位置上加盐,可以加任意的字符串
md5_obj.update(s.encode("utf-8"))
res = md5_obj.hexdigest()
print(res)

(4).动态加盐

例如:

import hashlib

name = input("请输入名字:")
password = input("请输入密码:")
md5_obj = hashlib.md5(name.encode("utf-8"))
md5_obj.update(password.encode("utf-8"))
res = md5_obj.hexdigest()
print(res) #用户名密码最后的摘要结果

2.hashlib模块第二个用法:文件的一执行校验

例子1:

import hashlib

md5_obj = hashlib.md5() #实例化一个对象
with open("file.py","rb")as f:
md5_obj.update(f.read())
ret1 = md5_obj.hexdigest()

md5_obj = hashlib.md5()
with open("file1.py","rb")as f1:
md5_obj.update(f1.read())
ret2 = md5_obj.hexdigest()

print(ret1,ret2) #(如果两个文件里的内容一致,打印出来结果一样)

例子2:对于同一个字符串,update一个,update多个结果一样

(1)

import hashlib

md5_obj = hashlib.md5()
md5_obj.update("hello,world".encode("utf-8"))
print(md5_obj.hexdigest())

(2)

md5_obj = hashlib.md5()
md5_obj.update("hello,".encode("utf-8"))
md5_obj.update("world".encode("utf-8"))
print(md5_obj.hexdigest())

九.configparser模块

原文地址:https://www.cnblogs.com/lhy979/p/9437408.html