Python——常用模块

原文:https://www.cnblogs.com/linhaifeng/articles/6384466.html

一、time与datetime模块

1.1 time

import time
# 时间分为三种格式:
# 1、时间戳:从1970年到现在经过的秒数
#		作用:用于时间间隔的计算
print(time.time())

# 2、按照某种格式显示的时间:2020-03-30 11:11:11
#		作用:用于展示时间
print(time.strftime('%Y-%m-%d %H:%M:%S %p'))
print(time.strftime('%Y-%m-%d %X'))

# 3、结构化的时间
#		作用:用于单独获取时间的某一部分
res=time.localtime()
print(res)
print(res.tm_year) # 获取当前年份
print(res.tm_mon) # 获取月份
print(res.tm_mday) # 获取每月第几天
print(res.tm_hour) # 获取当前是几点
print(res.tm_min) # 获取当前分钟
print(res.tm_sec) # 获取当前秒
print(res.tm_wday) # 获取星期几(0-6【星期天-星期六】)
print(res.tm_yday) # 获取当年已过去的天数


# 时间模块需要掌握的操作
# 1、时间格式的转换
# struct_time->时间戳
s_time=time.localtime()
print(time.mktime(s_time))

# 时间戳->struct_time
tp_time=time.time()
print(time.localtime(tp_time))

# 补充:世界标准时间与本地时间
print(time.localtime())
print(time.gmtime()) # 世界标准时间,了解
print(time.localtime(333333333))
print(time.gmtime(333333333))


# struct_time->格式化的字符串形式的时间
s_time=time.localtime()
print(time.strftime('%Y-%m-%d %H:%M:%S',s_time))

print(time.strptime('1988-03-03 11:11:11','%Y-%m-%d %H:%M:%S'))


# !!!真正需要掌握的只有一条:format string<------>timestamp
# '1988-03-03 11:11:11'+7

format string--->struct_time--->timestamp
struct_time=time.strptime('1988-03-03 11:11:11','%Y-%m-%d %H:%M:%S')
timestamp=time.mktime(struct_time)+7*86400
print(timestamp)

format string<---struct_time<---timestamp
res=time.strftime('%Y-%m-%d %X',time.localtime(timestamp))
print(res)

time.sleep(3)

# 了解知识
import time
print(time.asctime())

1.2 datetime

import datetime
# 获取当前时间以及计算三天后的时间
now_time = datetime.datetime.now().strftime('%Y-%m-%d %X')
print(now_time)
stop_time = datetime.datetime.now() + datetime.timedelta(days=3)
print(stop_time.strftime('%Y-%m-%d %X'))

1.3 time模块时间三种格式的转换

time模块——时间三种格式的转换.png

二、random模块

2.1 random

import random

print(random.random()) #(0,1)----float    大于0且小于1之间的小数
print(random.randint(1, 3))  # [1,3]    大于等于1且小于等于3之间的整数

print(random.randrange(1, 3))  # [1,3)    大于等于1且小于3之间的整数

print(random.choice([111, 'aaa', [4, 5]]))  # 1或者23或者[4,5]

print(random.sample([111, 'aaa', 'ccc','ddd'],2))  # 列表元素任意2个组合

print(random.uniform(1, 3))  # 大于1小于3的小数,如1.927109612082716

item = [1, 3, 5, 7, 9]
random.shuffle(item)  # 打乱item的顺序,相当于"洗牌"
print(item)


# 应用:随机验证码
def random_code():
    import random
    code = ''
    for i in range(6):
        s1 = chr(random.randint(97, 122))  # 小写字母ASCII码——>97-122
        s2 = chr(random.randint(65, 90))   # 大写字母ASCII码——>65-90
        s3 = str(random.randint(0, 9))
        code += random.choice([s1, s2, s3])
    return code

code = random_code()
print(code)

三、 os模块

3.1 os

'''
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  运行shell命令,直接显示
os.environ  获取系统环境变量
'''

# os.path系列
'''
os.path.abspath(path)  返回path规范化的绝对路径
os.path.split(path)  将path分割成目录和文件名二元组返回
os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path)  返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是绝对路径,返回True
os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小
'''

四、sys模块

4.1 sys

'''
1 sys.argv           命令行参数List,第一个元素是程序本身路径
2 sys.exit(n)        退出程序,正常退出时exit(0)
3 sys.version        获取Python解释程序的版本信息
4 sys.maxint         最大的Int值
5 sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
6 sys.platform       返回操作系统平台名称
'''

#=========知识储备==========
#进度条的效果
[#             ]
[##            ]
[###           ]
[####          ]

#指定宽度
print('[%-15s]' %'#')
print('[%-15s]' %'##')
print('[%-15s]' %'###')
print('[%-15s]' %'####')

#打印%
print('%s%%' %(100)) #第二个%号代表取消第一个%的特殊意义

#可传参来控制宽度
print('[%%-%ds]' %50) #[%-50s]
print(('[%%-%ds]' %50) %'#')
print(('[%%-%ds]' %50) %'##')
print(('[%%-%ds]' %50) %'###')

    
# 应用:实现进度条功能
import time

def progress(file_size, download_size=0):
    def wrapper(percent):
        if percent > 1:
            percent = 1
        bar = '#' * int(percent * 70)
        print('\r[%-70s] %d%%' % (bar, int(percent*100)), end='')
    while download_size <= file_size:
        time.sleep(0.1)
        download_size += 1024
        percent = download_size / file_size
        wrapper(percent)

progress(222222)
    	

五、shutil模块

高级的 文件、文件夹、压缩包 处理模块

shutil.copyfileobj(fsrc, fdst[, length])

将文件内容拷贝到另一个文件中

1 import shutil
2  
3 shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))

shutil.copyfile(src, dst)

拷贝文件

1 shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在

shutil.copymode(src, dst)

仅拷贝权限。内容、组、用户均不变

1 shutil.copymode('f1.log', 'f2.log') #目标文件必须存在

shutil.copystat(src, dst)

仅拷贝状态的信息,包括:mode bits, atime, mtime, flags

1 shutil.copystat('f1.log', 'f2.log') #目标文件必须存在

shutil.copy(src, dst)

拷贝文件和权限

1 import shutil
2  
3 shutil.copy('f1.log', 'f2.log')

shutil.copy2(src, dst)

拷贝文件和状态信息

1 import shutil
2  
3 shutil.copy2('f1.log', 'f2.log')

shutil.ignore_patterns(*patterns)

shutil.copytree(src, dst, symlinks=False, ignore=None)

递归的去拷贝文件夹

1 import shutil
2  
3 shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除 
import shutil

shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))

'''
通常的拷贝都把软连接拷贝成硬链接,即对待软连接来说,创建新的文件
'''

shutil.rmtree(path[, ignore_errors[, onerror]])

递归的去删除文件

1 import shutil
2  
3 shutil.rmtree('folder1')

shutil.move(src, dst)

递归的去移动文件,它类似mv命令,其实就是重命名。

1 import shutil
2  
3 shutil.move('folder1', 'folder3')

shutil.make_archive(base_name, format,...)

创建压缩包并返回文件路径,例如:zip、tar

创建压缩包并返回文件路径,例如:zip、tar

  • base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
    如 data_bak =>保存至当前路径
    如:/tmp/data_bak =>保存至/tmp/
  • format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
  • root_dir: 要压缩的文件夹路径(默认当前目录)
  • owner: 用户,默认当前用户
  • group: 组,默认当前组
  • logger: 用于记录日志,通常是logging.Logger对象
1 #将 /data 下的文件打包放置当前程序目录
2 import shutil
3 ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
4   
5   
6 #将 /data下的文件打包放置 /tmp/目录
7 import shutil
8 ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data') 

shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:

import zipfile

# 压缩
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()

# 解压
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall(path='.')
z.close()
import tarfile

# 压缩
>>> t=tarfile.open('/tmp/egon.tar','w')
>>> t.add('/test1/a.py',arcname='a.bak')
>>> t.add('/test1/b.py',arcname='b.bak')
>>> t.close()


# 解压
>>> t=tarfile.open('/tmp/egon.tar','r')
>>> t.extractall('/egon')
>>> t.close()

六、json&pickle模块

6.1 什么是序列化

  • 序列化是指把内存的数据类型转换成一个特定的格式内容,该格式的内容可用于存储或者传输给其他平台使用

  • 内存中的数据类型——>序列化——>特定的格式(json格式或者pickle格式)

  • 内存中的数据类型<——反序列化<——特定的格式(json格式或者pickle格式)

    # 土办法
    '''
    {'aaa': 111}——>序列化str({'aaa': 111})——>"{'aaa':111}"
    {'aaa': 111}<——反序列化eval("{'aaa':111}")<——"{'aaa':111}"
    '''
    

6.2 为何要序列化

  • 序列化得到结果——>特定的格式的内容有两种用途

  • 1、可用于存储===>用于存档

  • 2、传输给其他平台使用===>跨平台数据交互

    '''
    python                  java
     列表       特定的格式     数组
     
     
     强调:
     	针对用途1的特定格式:可以是一种专用的格式——> pickle只有python可以识别
     	针对用途2的特定格式:应该是一种通用的,能够被所有语言识别的格式——> json
    '''
    

6.3 序列化与反序列化的使用

# 序列化
import json
# 序列化的复杂方法
json_res = json.dumps([1, 'aa', True, False, [1,2,3], {'b':11}])
with open('test.json', 'wt', encoding='utf-8') as f:
    f.write(json_res)
    
# 序列化的简单方法
with open('test.json', 'wt', encoding='utf-8') as f:
    json.dump([1, 'aa', True, False, [1,2,3], {'b':11}], f)
    
# 反序列化
# 反序列化操作的复杂方法
with open('test.json', 'rt', encoding='utf-8') as f:
    json_res = f.read()
    loads_res = json.loads(json_res)
    print(loads_res)
    
# 反序列化操作的简单方法
with open('test.json', 'rt', encoding='utf-8') as f:
    loads_res = json.load(f)
    print(loads_res)
    
    
# json验证:json格式兼容的是所有语言通用的数据类型,不能使用独有的数据类型
json.dumps({1,2,3})

# json强调:一定要搞清楚json格式,不能与python混淆
l=json.loads('[1, "aaa", true, false]')
l=json.loads("[1,1.3,true,'aaa', true, false]")
print(l[0])

# 在python解释器2.7与3.6之后都可以json.loads(bytes类型),但唯独3.5不可以
res=json.dumps({'name':'哈哈哈'})
print(res,type(res))

res=json.loads('{"name": "\u54c8\u54c8\u54c8"}')
print(res,type(res))

6.4 猴子补丁与ujson

  • 6.4.1 什么是猴子补丁

    • 猴子补丁的核心就是用自己的代码替换所用模块的源代码
  • 6.4.2 猴子补丁的功能(一切皆对象)

    • 拥有在模块运行时替换的功能, 例如: 一个函数对象赋值给另外一个函数对象(把函数原本的执行的功能给替换了)
    class Monkey:
        def hello(self):
            print('hello')
    
        def world(self):
            print('world')
    
    
    def other_func():
        print("from other_func")
    
    
    
    monkey = Monkey()
    monkey.hello = monkey.world
    monkey.hello()
    monkey.world = other_func
    monkey.world()
    
  • 6.4.3 monkey patch的应用场景

    '''
    如果我们的程序中已经基于json模块编写了大量代码了,发现有一个模块ujson比它性能更高,
    但用法一样,我们肯定不会想所有的代码都换成ujson.dumps或者ujson.loads,那我们可能
    会想到这么做
    '''
    import ujson as json,但是这么做的需要每个文件都重新导入一下,维护成本依然很高
    此时我们就可以用到猴子补丁了
    只需要在入口处加上
    , 只需要在入口加上:
    
    import json
    import ujson
    
    def monkey_patch_json():
        json.__name__ = 'ujson'
        json.dumps = ujson.dumps
        json.loads = ujson.loads
    
    monkey_patch_json() # 之所以在入口处加,是因为模块在导入一次后,后续的导入便直接引用第一次的成果
    
    #其实这种场景也比较多, 比如我们引用团队通用库里的一个模块, 又想丰富模块的功能, 除了继承之外也可以考虑用Monkey
    Patch.采用猴子补丁之后,如果发现ujson不符合预期,那也可以快速撤掉补丁。个人感觉Monkey
    Patch带了便利的同时也有搞乱源代码的风险!
    
    

6.5 pickle模块

import pickle
res = pickle.dumps({1,2,3,4,5})
print(res, type(res))
s = pickle.loads(res)
print(s, type(s))

# pickle的序列化与反序列化
f=open('序列化对象_pickle','wb')#注意是w是写入str,wb是写入bytes,j是'bytes'
f.write(j)  #-------------------等价于pickle.dump(dic,f)

f.close()
#-------------------------反序列化
import pickle
f=open('序列化对象_pickle','rb')

data=pickle.loads(f.read())#  等价于data=pickle.load(f)

print(data['age'])   

# python2与python3的pickle兼容性问题
# coding:utf-8
import pickle

with open('a.pkl',mode='wb') as f:
    # 一:在python3中执行的序列化操作如何兼容python2
    # python2不支持protocol>2,默认python3中protocol=4
    # 所以在python3中dump操作应该指定protocol=2
    pickle.dump('你好啊',f,protocol=2)

with open('a.pkl', mode='rb') as f:
    # 二:python2中反序列化才能正常使用
    res=pickle.load(f)
    print(res)

七、shelve模块(了解)

7.1 shelve模块

  • shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型
import shelve

f=shelve.open(r'sheve.txt')
# f['stu1_info']={'name':'egon','age':18,'hobby':['piao','smoking','drinking']}
# f['stu2_info']={'name':'gangdan','age':53}
# f['school_info']={'website':'http://www.pypy.org','city':'beijing'}

print(f['stu1_info']['hobby'])
f.close()

八、xml模块(了解)

8.1 xml模块

  • xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。
# xml的格式如下,就是通过<>节点来区别数据结构的:
<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>
  • xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:

    # print(root.iter('year')) #全文搜索
    # print(root.find('country')) #在root的子节点找,只找一个
    # print(root.findall('country')) #在root的子节点找,找所有
    
    import xml.etree.ElementTree as ET
     
    tree = ET.parse("xmltest.xml")
    root = tree.getroot()
    print(root.tag)
     
    #遍历xml文档
    for child in root:
        print('========>',child.tag,child.attrib,child.attrib['name'])
        for i in child:
            print(i.tag,i.attrib,i.text)
     
    #只遍历year 节点
    for node in root.iter('year'):
        print(node.tag,node.text)
    #---------------------------------------
    
    import xml.etree.ElementTree as ET
     
    tree = ET.parse("xmltest.xml")
    root = tree.getroot()
     
    #修改
    for node in root.iter('year'):
        new_year=int(node.text)+1
        node.text=str(new_year)
        node.set('updated','yes')
        node.set('version','1.0')
    tree.write('test.xml')
     
     
    #删除node
    for country in root.findall('country'):
       rank = int(country.find('rank').text)
       if rank > 50:
         root.remove(country)
     
    tree.write('output.xml')
    
    #在country内添加(append)节点year2
    import xml.etree.ElementTree as ET
    tree = ET.parse("a.xml")
    root=tree.getroot()
    for country in root.findall('country'):
        for year in country.findall('year'):
            if int(year.text) > 2000:
                year2=ET.Element('year2')
                year2.text='新年'
                year2.attrib={'update':'yes'}
                country.append(year2) #往country节点下添加子节点
    
    tree.write('a.xml.swap')
    
  • 自己创建xml文档:

    import xml.etree.ElementTree as ET
     
     
    new_xml = ET.Element("namelist")
    name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
    age = ET.SubElement(name,"age",attrib={"checked":"no"})
    sex = ET.SubElement(name,"sex")
    sex.text = '33'
    name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
    age = ET.SubElement(name2,"age")
    age.text = '19'
     
    et = ET.ElementTree(new_xml) #生成文档对象
    et.write("test.xml", encoding="utf-8",xml_declaration=True)
     
    ET.dump(new_xml) #打印生成的格式
    

九、configparser模块

9.1 .ini配置文件

  • .ini配置文件
# 注释1
; 注释2

[section1]
k1 = v1
k2:v2
user=egon
age=18
is_admin=true
salary=31

[section2]
k1 = v1
  • 读取

    import configparser
    
    config=configparser.ConfigParser()
    config.read('a.cfg')
    
    #查看所有的标题
    res=config.sections() #['section1', 'section2']
    print(res)
    
    #查看标题section1下所有key=value的key
    options=config.options('section1')
    print(options) #['k1', 'k2', 'user', 'age', 'is_admin', 'salary']
    
    #查看标题section1下所有key=value的(key,value)格式
    item_list=config.items('section1')
    print(item_list) #[('k1', 'v1'), ('k2', 'v2'), ('user', 'egon'), ('age', '18'), ('is_admin', 'true'), ('salary', '31')]
    
    #查看标题section1下user的值=>字符串格式
    val=config.get('section1','user')
    print(val) #egon
    
    #查看标题section1下age的值=>整数格式
    val1=config.getint('section1','age')
    print(val1) #18
    
    #查看标题section1下is_admin的值=>布尔值格式
    val2=config.getboolean('section1','is_admin')
    print(val2) #True
    
    #查看标题section1下salary的值=>浮点型格式
    val3=config.getfloat('section1','salary')
    print(val3) #31.0
    
  • 改写

    import configparser
    
    config=configparser.ConfigParser()
    config.read('a.cfg',encoding='utf-8')
    
    
    #删除整个标题section2
    config.remove_section('section2')
    
    #删除标题section1下的某个k1和k2
    config.remove_option('section1','k1')
    config.remove_option('section1','k2')
    
    #判断是否存在某个标题
    print(config.has_section('section1'))
    
    #判断标题section1下是否有user
    print(config.has_option('section1',''))
    
    
    #添加一个标题
    config.add_section('egon')
    
    #在标题egon下添加name=egon,age=18的配置
    config.set('egon','name','egon')
    config.set('egon','age',18) #报错,必须是字符串
    
    
    #最后将修改的内容写入文件,完成最终的修改
    config.write(open('a.cfg','w'))
    
    import configparser
      
    config = configparser.ConfigParser()
    config["DEFAULT"] = {'ServerAliveInterval': '45',
                          'Compression': 'yes',
                         'CompressionLevel': '9'}
      
    config['bitbucket.org'] = {}
    config['bitbucket.org']['User'] = 'hg'
    config['topsecret.server.com'] = {}
    topsecret = config['topsecret.server.com']
    topsecret['Host Port'] = '50022'     # mutates the parser
    topsecret['ForwardX11'] = 'no'  # same here
    config['DEFAULT']['ForwardX11'] = 'yes'
    with open('example.ini', 'w') as configfile:
       config.write(configfile)
    

十、hashlib模块

10.1 hashlib模块

# 1、什么叫hash:
#1.1 hash是一种算法,该算法接受传入的内容,经过运算得到一串hash值
# 2、hash值的特点是:
#2.1 只要传入的内容一样,得到的hash值必然一样=====>要用明文传输密码文件完整性校验
#2.2 不能由hash值返解成内容=======》把密码做成hash值,不应该在网络传输明文密码
#2.3 只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的

# hash的用途
# 用途1:特点2用于密文与密文的传输与验证
# 用途2:特点1,3用于文件内容完整性校验
  • hash算法就像一座工厂,工厂接收你送来的原材料(可以用m.update()为工厂运送原材料),经过加工返回的产品就是hash值

img

import hashlib

m=hashlib.md5()# m=hashlib.sha256()

m.update('hello'.encode('utf8'))
print(m.hexdigest())  #5d41402abc4b2a76b9719d911017c592

m.update('alvin'.encode('utf8'))

print(m.hexdigest())  #92a7e713c30abbb0319fa07da2a5c4af

m2=hashlib.md5()
m2.update('helloalvin'.encode('utf8'))
print(m2.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af

'''
注意:把一段很长的数据update多次,与一次update这段长数据,得到的结果一样
但是update多次为校验大文件提供了可能。
'''
  • 以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。

    import hashlib
    
    # ######## 256 ########
    
    hash = hashlib.sha256('898oaFs09f'.encode('utf8'))
    hash.update('alvin'.encode('utf8'))
    
    #e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7
    print (hash.hexdigest())
    
    

10.2 模拟撞库破解密码

import hashlib
passwds=[
    'alex3714',
    'alex1313',
    'alex94139413',
    'alex123456',
    '123456alex',
    'a123lex',
    ]
def make_passwd_dic(passwds):
    dic={}
    for passwd in passwds:
        m=hashlib.md5()
        m.update(passwd.encode('utf-8'))
        dic[passwd]=m.hexdigest()
    return dic

def break_code(cryptograph,passwd_dic):
    for k,v in passwd_dic.items():
        if v == cryptograph:
            print('密码是===>\033[46m%s\033[0m' %k)

cryptograph='aee949757a2e698417463d47acac93df'
break_code(cryptograph,make_passwd_dic(passwds))
  • python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 进行进一步的处理然后再加密:

    import hmac
    h1=hmac.new('hello'.encode('utf-8'),digestmod='md5')
    h1.update('world'.encode('utf-8'))
    
    print(h1.hexdigest())
    
    #要想保证hmac最终结果一致,必须保证:
    #1:hmac.new括号内指定的初始key一样
    #2:无论update多少次,校验的内容累加到一起是一样的内容
    
    # 操作一
    import hmac
    h1=hmac.new('hello'.encode('utf-8'),digestmod='md5')
    h1.update('world'.encode('utf-8'))
    
    print(h1.hexdigest()) # 0e2564b7e100f034341ea477c23f283b
    
    # 操作二
    import hmac
    h2=hmac.new('hello'.encode('utf-8'),digestmod='md5')
    h2.update('w'.encode('utf-8'))
    h2.update('orld'.encode('utf-8'))
    
    print(h1.hexdigest()) # 0e2564b7e100f034341ea477c23f283b
    

十一、suprocess模块

11.1 subprocess模块

'''
sh-3.2# ls /Users/egon/Desktop |grep txt$
mysql.txt
tt.txt
事物.txt
'''

res1=subprocess.Popen('ls /Users/jieli/Desktop',shell=True,stdout=subprocess.PIPE)
res=subprocess.Popen('grep txt$',shell=True,stdin=res1.stdout,
                 stdout=subprocess.PIPE)

print(res.stdout.read().decode('utf-8'))


#等同于上面,但是上面的优势在于,一个数据流可以和另外一个数据流交互,可以通过爬虫得到结果然后交给grep
res1=subprocess.Popen('ls /Users/jieli/Desktop |grep txt$',shell=True,stdout=subprocess.PIPE)
print(res1.stdout.read().decode('utf-8'))


#windows下:
# dir | findstr 'test*'
# dir | findstr 'txt$'
import subprocess
res1=subprocess.Popen(r'dir C:\Users\Administrator\PycharmProjects\test\函数备课',
                      shell=True,stdout=subprocess.PIPE)
res=subprocess.Popen('findstr test*',shell=True,stdin=res1.stdout,
                 stdout=subprocess.PIPE)

# subprocess使用当前系统默认编码,得到结果为bytes类型,在windows下需要用gbk解码
print(res.stdout.read().decode('gbk'))
posted @ 2020-03-30 19:31  群青-Xi  阅读(137)  评论(0编辑  收藏  举报