模块(module)的概念:

为了维护代码(最大的好处),把很多函数分组,分别放到不同的文件里;在Python中,一个.py文件就是就称之为一个模块

其次,编写代码不必从零开始,当一个模块编写完毕,就可以在其他地方被引用。模块一共分3种:1)python标准库;2)第三方模块;3)应用程序自定义模块。(自己写模块时不要和已有的模块 重名,或者新建文件夹建重名的)

#文件夹和python packa的区别:包里面会多一个_init_.py的空文件,包的功能是组织模块:存放某一功能的各种模块,方便存放与取用。 

引用模块时,要注意路径,如果与执行文件在同一级文件时可以直接引用,如果在执行文件的下一层,可以相对引用。(只能识别与执行文件所在的同一层级,其他的引用都要加相对或者绝对引用)

引入其他自写模块时,都以当前执行文件的模块为路径进行查找,而不会以引入模块的路径去查找

# import cal    #引入模块时:1.执行对应py文件(全部执行);2.引入变量名     (cal模块是自己编写的)
# print(cal.add(3,5))
#
# # from functools import *           #引入包里的全部变量,不推荐此方法,里面的函数名称太多,可能和自己写的函数名相同
# from functools import reduce
# print(reduce(lambda x,y:x*y,[3,4,5]))

# from my_module import cal_new   #相对引用,cal_new.py是下层文件
 # print(cal_new.add(3,5))

# from my_module.web1.cal import add   #从当前路径开始引用更深层次路径的py文件
# print(add(3,4))

# from my_module.web1 import cal #也可以调用,和上面功能相同
# print(cal.add(3,4))

# from my_module import web1 #不可以,这个执行的是_init_.py文件
# print(web1.cal.add(3,4))
 

 

__name__的两个意义:

在执行文件打印的时候就是字符串__main__;在调用文件里打印时就是打印调用文件的地址
print('ok0')

def add(x,y):
    print('ok1')
    return x+y

def sub(x,y):
    print('ok2')
    return x-y

print(__name__)

if __name__ == '__main__':      #做调用文件时:用于被调用函数的测试;做执行文件时:在别人调用函数时不启动主程序,自己执行时才启动
    print(add(3,4))

 

time模块:

import time

# #时间戳
# print(time.time())                #从1970年1月1日到现在一共经历了多少秒

# #结构化时间
# print(time.localtime())           #本地的结构化时间
#
# t=time.localtime()
# print(t.tm_year)
# print(t.tm_wday)
#
# print(time.gmtime())              #世界标准时间的结构化时间(格林威尔时间,与东八区差8小时)

# #结构化时间——时间戳,由时间戳转化为结构化时间就是localtime和gmtime,默认参数就是当前时间戳;结构化时间转化为时间戳,用mktime
# print(time.localtime(1609730674.0720983))
# print(time.mktime(time.localtime()))

# #结构化时间——字符串时间,由结构化时间转换成字符串时间用strftime,将字符串转换为结构化时间用strptime
# print(time.strftime('%Y-%m-%d %X',time.localtime()))          #X表示时分秒
# print(time.strptime('2021:01:04:12:04:56','%Y:%m:%d:%X'))

# print(time.asctime())       #将结构化时间转换成固定格式的字符串时间,不用写格式,更便利
# print(time.ctime())         #将时间戳转换成固定格式的字符串时间,不用写格式,更便利

#time.sleep()线程推迟指定的时间运行,单位为秒。

# import datetime                     #另一个模块下的显示时间
# print(datetime.datetime.now())

 

random模块:

import random

# print(random.random())    #随机取(0,1)的float
# print(random.uniform(0,2))#随机取范围内的float
# print(random.randint(1,3))  #随机取[1,3]的整数
# print(random.randrange(1,3))  #随机取[1,3)的整数
# print(random.choice([11,22,33,44]))   #随机选取一个列表里的元素,可以依据元素个数定比例
# print(random.sample([11,22,33,44],2))   #随机选取列表里的规定个数的元素,组成新列表

# ret = [1,3,5,7,9]
# random.shuffle(ret)         #打乱列表的顺序
# print(ret)

#练习:制作5位随机验证码
def v_code():
    ret=''
    for i in range(5):
        num=random.randint(0,9)
        alp=chr(random.randint(65,122))         #chr在ASCII中根据数字取字母
        s=str(random.choice([num,alp]))
        ret += s
    return ret
print(v_code())

 

os模块:

import os

# print(os.getcwd())            #获取当前工作文件的目录路径

# os.chdir("..")                #改变工作脚本的目录,相当于shell下的cd
# print(os.getcwd())
# os.chdir('python练习')
# print(os.getcwd())

# os.curdir                       #代表返回当前目录,也可用os.chdir(".")
# print(os.getcwd())

# os.pardir                       #,代表获取当前目录的父目录字符串名,也可用os.chdir("..")
# print(os.getcwd())

# os.makedirs('text1/text2')         #在当前目录建立递归文件目录
# os.removedirs('text1/text2')         #删除目录文件,如果目录文件不为空,则不能删,要指定全部删才能删掉
# os.remove()                           #也是删除文件,与上面一样

# print(os.listdir())                 #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印

# print(os.stat('人口普查'))            #获取文件或目录信息

# print(os.sep)                         #输出操作系统特定的路径分隔符(win:"\"   linux:"/")在不清楚操作系统下使用

# print(os.linesep)                      #输出操作系统特定的行终止符(win:"\r\n"    linux:"\n")在不清楚操作系统下使用

# print(os.pathsep)                     #输出操作系统用于分割文件路径的字符串(win:";"   linux:":")

# print(os.name)                         #输出字符串指示当前使用平台(win:"nt"   linux:"posix")

# print(os.system('time模块.py'))          #运行shell命令,直接显示指定文件

# print(os.environ)                       #获取系统环境变量

# print(os.path.split(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py'))     #将path分割成目录和文件名,以元组返回
# print(os.path.dirname(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py'))   #返回path目录,即上顺元组的第一个值
# print(os.path.basename(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py'))  #返回path文件名,即上顺元组的第二个值(如果path以/或\结尾,返回空)
# print(os.path.exists(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py'))    #path是否存在(path以/或\结尾即不存在)

# print(os.path.isabs(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py'))         #如果是绝对路径,返回True
# print(os.path.isfile(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py'))        #如果是一个存在的文件,返回True
# print(os.path.isdir(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py'))         #如果是一个存在的目录 ,返回True

# #重点:
# a = "C:Users\Lenovo\Desktop"
# b = "python练习\sys模块.py"
# print(os.path.join(a,b))           #将多个路径组合后返回,第一个绝对路径之前的参数将被省略

# print(os.path.getatime(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py'))     #获取变量最后一次的访问时间
# print(os.path.getmtime(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py'))     #获取变量最后一次的修改时间

 

sys模块:

import sys
# sys.path.append()                #增加(修改)环境变量,这是暂时性的,永久的修改在计算机属性里

# import os
# print(os.path.dirname(os.path.abspath(__file__)))       #返回上一级路径,os.path.abspath(__file__)是当前位置文件的绝对地址
# print(os.path.abspath(__file__))

# print(sys.path)               #返回模块的搜索路径,初始化时使用pythonpath环境变量的值
# sys.exit()                   #退出程序,exit(0)为正常退出

# print(sys.version)              #获取python解释程序到的版本信息
# print(sys.platform)             #返回操作系统平台名称

# #重点
# print(sys.argv)              #在命令提示符执行,输出命令行参数list,第一个元素是程序本身路径,(有此参数后,命令提示符输入的其他值也可以保留下来,作为执行程序的启动指令)
# x = sys.argv[2]
# if sys.argv[1]=='sb':
#     print('sbbb')

# sys.stdout.write('#')      #打印内容,再次重复代码会在原来打印的内容上叠加
# sys.stdout.write('#')

# import time                       #制作进度条
# for i in range(10):
#     sys.stdout.write('#')
#     time.sleep(1)

 

json&pickle模块(数据交换):

import json

# dic = {'name':'lyt'}
# data = json.dumps(dic)        #将其他类型的数据转换为字符串类型的数据,且原数据里面的单引号均变为双引号(能够适用于各种编程语言)
# print(data)
# print(type(data))
#
# s = json.loads(data)
# print(s)
# print(type(s))                #将字符串类型的数据还原为json.dumps之前原来类型的数据(符合json字符串的没经过dumps也可以loads)(json封装后可作为一个桥梁,可以使数据在各种语言之间相互转换)

# f = open('json测试','w')
# # k=json.dumps(s)
# # f.write(k)
# json.dump(s,f)                 #相当于前两步,省略了写,不推荐

# g = open('json测试','r')
# e = json.load(g)                 #省略了读数据这一步,不推荐
# print(type(e))



import pickle

dic = {'name':'lyt'}
data = pickle.dumps(dic)           #将其他类型的数据转换为字节形式(pickle和json的dumps都称为序列化,pickle序列的类型更多)
print(type(data))

# f = open('pickle测试','wb')
# f.write(data)                      #w写入str,wb写入的是bytes

import pickle
k = open('pickle测试','rb')
t = pickle.loads(k.read())
print(t)

 

shelve模块:

#和json作用差不多,使用简单但使用的范围小
import shelve
f = shelve.open(r'shelve')         #目的:将一个字典放入文本
f['stu1_info']={'name':'alex','age':18}
f['stu1_info']={'name':'ppp','age':20}
f['school_info']={'websits':'zncj','city':'wh'}
f.close()

f = shelve.open(r'shelve')
print(f.get('stu1_info'))
print(f.get('stu1_info')['age'])

 

xml模块:

#作用和json相似,出现得更早,目前广泛应用
import xml.etree.ElementTree as ET

tree = ET.parse('xml_lesson1')   #读取
root = tree.getroot()            #拿到根节点(xml是一个树枝结构)
print(root.tag)                  #tag拿到的是标签名(在xml文件中为黄色),不是属性及值

for i in root:
    print(i.tag)
    for j in i:
        print(j.tag)
        print(j.attrib)          #attrib拿的是属性,以字典显示(在xml文件中有等号)
        print(j.text)            #text拿的是标签的值,(在xml文件中有夹在标签名之中)

for node in root.iter('year'):   #只遍历year节点
    print(node.tag,node.text)

    new_year = int(node.text) + 1 #修改
    node.text = str(new_year)
    node.set("updated","yes")     #增加属性
tree.write("xml_test.xml")        #这一步表示将内存里修改好的保存在硬盘

for country in root.findall('country'):
    rank = int(country.find('rank').text)
    if rank > 50:
        root.remove(country)
tree.write("output.xml")         #删除

#创建标签
new_xml = ET.Element("namelist")
name1 = ET.SubElement(new_xml,"name1",attrib={'enrolled':'yes'})
age = ET.SubElement(name1,"age",attrib={'cheched':'no'})
sex = ET.SubElement(name1,'sex')
sex.text = '33'

name2 = ET.SubElement(new_xml,"name2",attrib={'enrolled':'no'})
age = ET.SubElement(name2,"age",attrib={'cheched':'no'})
sex = ET.SubElement(name2,'sex')
age.text = '19'
et = ET.ElementTree(new_xml)       #生成文档对象
et.write("new_list.xml",encoding="utf_8",xml_declaration=True)

 

re模块(正则表达式):

正则表达式是一种小型的、高度专业的编程语言,所有编程语言都可以用,内嵌在python中,通过re模块实现,用于处理字符串(比如模糊匹配)

1.普通字符:大多数字符和字母都会和自身匹配(精准匹配)

2.元字符:.  ^  $  *  +  ?  {}  []  |  ()  \

 

s = 'djfgndkwiodwndfnwdasklnnjlytncvsdnc'
print(s.find('lyt'))

# .为通配符,除了\n换行不行
import re
print(re.findall("l.t",'djfgndkwiodwndfnwdasklnnjlxtncvsdnc'))

# ^指只能在字符串开头匹配才能成功
print(re.findall("^l.t",'djfgndkwiodwndfnwdasklnnjlxtncvsdnc'))
print(re.findall("^d.f",'djfgndkwiodwndfnwdasklnnjlxtncvsdnc'))    #前三个字符必须是规定的

# $指只能在字符串结尾匹配才能成功
print(re.findall("s..c$",'djfgndkwiodwndfnwdasklnnjlxtncvsdnc'))   #后4个字符必须是规定的
print(re.findall("s..c$",'djfgndkwiodwndfnwdasklnnjlxtncvsdnc$'))  #不能匹配上,$在字符串中是普通字符,而非元字符

# *表示重复,重复紧挨着的字符串,可以重复0到无穷次;+也表示重复,可以重复1到无穷;?重复0或者一个(均为贪婪匹配,有多少匹配多少)
print(re.findall("s*",'djfgndkwiodwnssssdfnwdasklnnjlxtncvsdnc$'))
print(re.findall("alex*",'qweruhrnalexxxxjndn'))
print(re.findall("alex+",'qweruhrnalexxxxjndn'))
print(re.findall("alex*",'qweruhrnalejndn'))                     # x*的x起修饰作用,自身并不算一个
print(re.findall("alex+",'qweruhrnalejndn'))                     #+号不能匹配0个
print(re.findall("alex?",'qweruhrnalejndn'))
print(re.findall("alex?",'qweruhrnalexxjndn'))

#{0,}相当于*;{1,}相当于+;{0,1}相当于?;{6}表示固定几个;{a,b}表示范围。
print(re.findall("alex{6}",'qweruhrnalexxxxxxxjndn'))
print(re.findall("alex{6}",'qweruhrnalexxjndn'))

# 在贪婪匹配后加?表示惰性匹配,按最少的去匹配
print(re.findall("alex*?",'qweruhrnalexxxxjndn'))
print(re.findall("alex+?",'qweruhrnalexxxxjndn'))

#字符集[]表示或
print(re.findall("x[yz]",'xydfjjsxz'))         #findall返回所有满足匹配条件的结果,放在列表里
print(re.findall("x[yz]p",'xydfjjsxzp'))
print(re.findall("x[y,z]",'x,ydfjjsxzp'))      #在[]里逗号(,)或者星(*)等元字符算普通字符,除-(表示范围);^(表示非);\()是特殊意义
print(re.findall("x[y*z]",'x,ydfjjsx*zp'))
print(re.findall("x[a-z]",'x,ydfjjsxbp'))
print(re.findall("x[a-z]*",'x,ydfjjsxbp'))     #这里的*表示a到z的都可以重复
print(re.findall("x[^a-z]",'x,ydfjjsxbpx12'))     #除a-z中其他的都可匹配

# \后边跟元字符去除特殊功能;\后边跟普通字符实现特殊功能
print(re.findall("\d",'2345x,ydfjjsxbpx12'))    #d选出字符串中的数字,D取出非数字(大小写功能相反)
print(re.findall("\d+",'2345x,ydfjjsxbpx12'))
print(re.findall("\s",'2345x, ydfjjsxbpx12'))   #s取出空白,S取出所有非空白
print(re.findall("\S+",'2345x, ydfjjsxbpx12'))
print(re.findall("\w",'2345x, ydfjjsxbpx12'))   #w匹配所有字母数字字符,W相反
print(re.findall("\b",'2345x, y&dfjjs#xbpx12'))  #\b匹配一个特殊字符边界,比如空格,&,#等
print(re.findall("www\.baidu","www:baidu"))    #去掉特殊功能
print(re.findall("www.baidu","www:baidu"))

import re
print(re.findall('I',"Hello I am LISA"))
print(re.findall('^I',"Hello I am LISA"))
print(re.findall('^I',"I am LISA"))
print(re.findall('I\b',"Hello I am LISA")) #不能匹配出来,要用下两种方法
print(re.findall(r'I\b',"Hello I am LISA")) #\b表示匹配特殊字符,加上r表示python不进行任何转译,将内容直接传给re执行
print(re.findall('I\\b',"Hello I am LISA")) #\\表示python转译时去掉\的特殊意义,将内容传给re后有一个\,对应\b(多个\也遵循此逻辑)

print(re.findall('ka|b','sddjkasf'))
print(re.findall('ka|b','sddjkbsf'))
print(re.findall('ka|b','sddjkabsf')) #|表示或

print(re.findall('(a.c)','abcabcabc')) #()表示分组,把括号里的当作一个整体

print(re.search('(a.c)','adcabcabc')) #search表示匹配到第一个结果就返回,结果存在一个对象中,通过group取用;匹配失败返回空
print(re.search("(?P<name>[a-z]+)","alex20lyt18").group())
ret=re.search("(?P<name>[a-z]+)(?P<age>\d+)","alex20lyt18") #加入此格式表示分组并对组进行命名,<>为命名,方便查询不同组的数据(P为大写)
print(ret.group('name'))

print(re.match('\d+',"alex34lyt20")) #match跟search功能相同,但必须在开头匹配成功,相当于search('^\d+',"alex34lyt20")
print(re.split("[ |]","hello we|sdf")) #split 以指定符号为分隔符,切分文本(分隔符会被去掉)
print(re.split('[ab]','abc')) #split会将得到的结果再次分割,直到不能再分割了为止

print(re.sub('\d+','A','sdjf654fhgjd67')) #sub表示替换,一般需要三个参数
print(re.sub('\d+','A','sdjf654fhgjd67',1)) #第四个参数表示要替换的次数
print(re.subn('\d+','A','sdjf654fhgjd67')) #比sub功能多一个替换的次数

com=re.compile('\d+') #compile表示先编译模糊匹配的功能,后面直接用就行(可多次执行,效率比findall('\d+','ashdfh34ghehf56')高一点)
print(com.findall('ashdfh34ghehf56'))

print(re.finditer('\d+','ashdfh34ghehf56')) #区别在于findall的是,得到的是迭代器对象

print(re.findall("www\.(baidu|163)\.com","www.baidu.com")) #即使匹配成功,优先给出组里(即括号)的内容
print(re.findall("www\.(?:baidu|163)\.com","www.baidu.com")) #取消组的优先级

s = "12+(56-7*(7*8-2)+20)"
print(re.search("\([^()]+\)",s).group()) #查找最里层的括号里的内容

 

 

logging模块:

 

format参数中可能用到的格式化串:

%(name)s Logger的名字

%(levelno)s 数字形式的日志级别

%(levelname)s 文本形式的日志级别

%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有

%(filename)s 调用日志输出函数的模块的文件名

%(module)s 调用日志输出函数的模块名

%(funcName)s 调用日志输出函数的函数名

%(lineno)d 调用日志输出函数的语句所在的代码行

%(created)f 当前时间,用UNIX标准的表示时间的浮点数表示

%(relativeCreated)d 输出日志信息时的,自logger创建以来的毫秒数

%(asctime)s 字符串形式的当前时间

%(thread)d 线程ID,可能没有

%(threadName)s 线程名,可能没有

%(process)d 进程ID,可能没有

%(message)s 用户输出的消息

import logging
#
# logging.basicConfig(
#     level=logging.DEBUG,   #设置rootlogger的日志级别,可更换默认层级
#     filename='logger.log', #用指定的文件名创建FieldHandler,这样日志会被储存在指定的文件中(filename会将日志输出到文件,stream则将输出到屏幕)
#     filemode="w",           #设置写入(打开)方式,默认为a追加
#     format="%(asctime)s %(lineno)s %(message)s %(filename)s"  #指定日志的显示格式,往%()加入想要的格式就行
#     #datefmt指定日期时间格式
#     #stream指定的stream创建streamhandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为前者。若同时列出了filename和stream两个参数,则stream参数会被忽略
#     )
#
# logging.debug('debug message')
# logging.info('info message')
# logging.warning('Hello')
# logging.error('error message')
# logging.critical('critical message')        #表示在对应层级加入日志,级别越来越重要,默认的level是warning级别,只显示其以后的级别(包括自己)


# #logger对象
# def test():
#     logger=logging.getLogger()           #创建可吸收其他日志的对象
#     fh=logging.FileHandler("test_log")   #创建文件日志
#     ch=logging.StreamHandler()           #创建屏幕日志
#     fm=logging.Formatter("%(asctime)s %(message)s")#设置日志的格式
#     fh.setFormatter(fm)                  #将格式给予日志
#     ch.setFormatter(fm)
#     logger.addHandler(fh)                #吸收日志
#     logger.addHandler(ch)
#     logger.setLevel("DEBUG")
#     return logger
# #可将上述设置成一个函数以便需要时调用
# logger=test()
# logger.debug('debug message')
# logger.info('info message')
# logger.warning('Hello')
# logger.error('error message')
# logger.critical('critical message')


# logger1=logging.getLogger('mylogger')   #默认是root用户建立的对象,这里是子目录mylogger创建的,一个目录只能有一个级别,所以只能打印8条记录
# logger1.setLevel(logging.DEBUG)
#
# logger2=logging.getLogger('mylogger')
# logger2.setLevel(logging.INFO)
#
# fh=logging.FileHandler("test_log_NEW")
# ch=logging.StreamHandler()
# fm=logging.Formatter("%(asctime)s %(message)s")
# fh.setFormatter(fm)
# ch.setFormatter(fm)
#
# logger1.addHandler(fh)
# logger1.addHandler(ch)
#
# logger2.addHandler(fh)
# logger2.addHandler(ch)
#
# logger1.debug('debug message')
# logger1.info('info message')
# logger1.warning('Hello')
# logger1.error('error message')
# logger1.critical('critical message')
#
# logger2.debug('debug message')
# logger2.info('info message')
# logger2.warning('Hello')
# logger2.error('error message')
# logger2.critical('critical message')


logger=logging.getLogger()
logger.setLevel(logging.DEBUG)

logger1=logging.getLogger('mylogger')        #树形关系,mylogger是root的子目录,它打印时有几个父辈级就将自身的内容再多打印几份
logger1.setLevel(logging.INFO)

fh=logging.FileHandler("test_log_NEW1")
ch=logging.StreamHandler()
fm=logging.Formatter("%(asctime)s %(message)s")
fh.setFormatter(fm)
ch.setFormatter(fm)

logger.addHandler(fh)
logger.addHandler(ch)

logger1.addHandler(fh)
logger1.addHandler(ch)

logger.debug('debug message')
logger.info('info message')
logger.warning('Hello World')
logger.error('error message')
logger.critical('critical message')

logger1.debug('debug message')
logger1.info('info message')
logger1.warning('Hello')
logger1.error('error message')
logger1.critical('critical message')

 

 

configparser(配置文件解析)模块:

配置文件:类字典文件,包含块和值(键值对)

import configparser
# config = configparser.ConfigParser()      #相当于建了一个空字典{}
#
# config["DEFAULT"] = {'ServerAliveInterval':'45',
#                        'Compression':'yes',
#                        'CompressionLevel':'9',
#                        'ForwardXll':'yes'}  #给DEFAULT关键字对应值
#
# with open('example.ini','w')as f:
#     config.write(f)                         #把配置文件写入文件里


#配置文件的增删改查
config = configparser.ConfigParser()
config.read('example.ini')   #
print(config.sections())     #拿到除default外的块(即关键字)
print('bitbucket.org' in config)   #判断块在不在配置文件里
print(config['bitbucket.org']['user']) #在块下面取值,不区分大小写

for key in config['bitbucket.org']:     #遍历块的值的时候,都会遍历出默认块的值(块的值也是一个字典)
    print(key)

print(config.options('bitbucket.org'))  #与for循环的遍历功能相似,取出值对应的字典的键,输出为一个列表
print(config.items('bitbucket.org'))    #取出块的值,输出为一个列表
print(config.get('bitbucket.org','user')) #取出块的值对应的字典的值

config.add_section('yuan')               #增加块
config.set('yuan','k1','1111')           #添加块下的值
config.write(open('i.cfg','w'))

config.remove_section('yuan')            #删除块
config.remove_option('bitbucket.org','port')   #删除块对应的某些值
config.write(open('i-1.cfg','w'))

 

配置文件范例:

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardXll = yes

[bitbucket.org]
User = hg

[topsecret.server.com]
Port = 50022
ForwardXll = no

 

 

hashlib模块:

用于加密相关操作,python3里代替了md5模块和sha模块,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法。(摘要算法,将明文转换为密文,单向操作)

位数是固定的,均为32位

import hashlib

obj = hashlib.md5()
obj.update('hello'.encode("utf8"))
print(obj.hexdigest())              #普通的加密,得到原生的hash值,容易通过数据库中hash值与明文的对应进行反解

#加盐,生成的密文变成独一无二的hash值
obj = hashlib.md5('lyt'.encode("utf8"))
obj.update('hello'.encode("utf8"))     #如果第一段代码执行,再执行这一段代码,相当于执行update('hellohello'),即叠加
print(obj.hexdigest())                 #其他算法与此类似,更换算法名即可

 

posted on 2021-01-20 17:36  yutianray  阅读(98)  评论(0)    收藏  举报