zoukankan      html  css  js  c++  java
  • Python模块

     一、模块

    模块就是写好的功能放在一个文件里,即py文件

     

    模块的种类:

    ① 内置模块:安装python解释器的时候就装上了

    ② 第三方模块、扩展模块:不在内置模块不一定不重要,根据用户需求安装使用

    ③ 自定义模块:自己写的py文件

     

    二、序列化模块

    序列:列表、元组、字符串、bytes

    序列化:把一个数据类型转换成字符串、bytes类型的过程就是序列化

     

    数据类型序列化的场景:

    ① 把一个数据类型存储在文件中

    ② 把一个数据类型通过网络传输的时候

     

    eval和exec:用户输入,文件读入,网络传入都不能使用,存在风险,极其不安全。

     

    import json    # 导入json模块

    在json格式下,所欲的字符串都是双引号。

     

    json.dumps(obj)   序列化的过程,转换为字符串

    import json                                     # 导入json模块
    dic = {'province':'广东省','city':'深圳市'}
    s = json.dumps(dic)                             # 序列化的过程
    print(s,type(s))
    
    # {"province": "u5e7fu4e1cu7701", "city": "u6df1u5733u5e02"} <class 'str'>

     

    json.loads(str)    反序列化的过程,转换为原本的类型

    import json                                         # 导入json模块
    dic = {'province':'广东省','city':'深圳市'}
    s = json.dumps(dic)                                 # 序列化的过程
    dic2 = json.loads(s)                                # 反序列化的过程
    print(dic2,type(dic2))
    
    # {'province': '广东省', 'city': '深圳市'} <class 'dict'>

     

    json.dump(obj,f)     序列化的过程,将字典写入到文件中

    import json
    dic = {'a':1,'lis':[1,2,3],'city':'gz'}
    f = open('aaa','a',encoding='utf-8')
    json.dump(dic,f)                        # 把字典写入到文件中
    f.close()
    
    '''
    {"a": 1, "lis": [1, 2, 3], "city": "gz"}
    '''

     

     json.load(f)

    import json
    f = open('aaa',encoding='utf-8')
    dic = json.load(f)              # 将文件的内容读取出来,并且还原原来的类型
    print(dic)                      # {'a': 1, 'lis': [1, 2, 3], 'city': 'gz'}

     

    json的优点:

    ① 所有的语言都通用

    json的缺点:

    ① 只支持非常少的数据类型

    ② 对数据类型的约束很苛刻

    ③ 字典的key必须是字符串

    ④ 只支持数据类型:数字、字符串、列表、字典 

     

    使用json的场景:

      序列化的内容是简单的内容,比如字典,字符串类型的就选择json,因为json有优势,可以直接看到结果,或者从文件里 能看到结果。

      前端使用的是json,网络传输的数据大部分也是使用json

     

    json的特点:

    ① 可以在所有的语言中通用

    ② 能够处理的数据类型非常优先(网络操作中,以及多语言环境中,传递字典、数字、字符串、列表等简单的数据类型时使用)

    ③ json的字典有非常苛刻的要求:字典的key必须是字符串,且所有的字符串都必须是用" " 表示

    ④ dumps(dict/list) 把dict/list 转化成str,这是序列化

    ⑤ loads(str) 把str转化为dict/list,这是反序列化

    ⑥ dump(dict/list,f) 把dict/list写入文件,这是序列化

    ⑦ load(f) 文件转化为原来的数据类型,这是反序列化

    ⑧ 多次dump进入文件中的数据load会报错

     

    json的参数:

    ensure_ascii:默认值True,如果dict内含有non-ASCII的字符,则会类似uXXXX的显示数据,设置成False后,就能正常显示

    indent:应该是一个非负的整型,如果是0,或者为空,则一行显示数据,否则会换行且按照indent的数量显示前面的空白,这样打印出来的json数据也叫pretty-printed json

    separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(',',':');这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。

    encoding:默认是UTF-8,设置json数据的编码方式。

    sort_keys:将数据根据keys的值进行排序。

     

    pickle

    import pickle

    pickle和json的用法相似。

     

    局限性:只有python语言支持

    优点:支持几乎所有的数据类型

     

    pickle操作文件必须是以+b的形式

    pickle支持多次dump和多次load,需要使用try...except

     

    ① pickle多次dump

    import pickle
    lis = [1,2,3,{'a':1,'b':2,'c':['a','b','c'],'d':'gz'},'z','x']
    f = open('aaa','ab')
    for i in range(10):
        pickle.dump(lis,f)          # 循环多次写入文件
    f.close()

     

    ② pickle多次load

    import pickle
    f = open('aaa','rb')
    while 1:
        try:
            lis = pickle.load(f)
            print(lis)
        except EOFError:
            break
    f.close()
    
    '''
    [1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
    [1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
    [1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
    [1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
    [1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
    [1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
    [1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
    [1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
    [1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
    [1, 2, 3, {'a': 1, 'b': 2, 'c': ['a', 'b', 'c'], 'd': 'gz'}, 'z', 'x']
    '''

     

    三、时间模块

    imprt time

     

    三种格式:

    ① 时间戳时间:浮点数支撑,以秒为单位(方便计算机计算)

    语法:time.time()

    1970-1-1 0:0:0 格林威治时间,时间的起始点

    import time
    t = time.time()
    print(t)            # 1536047063.2101386

     

    ② 格式化时间:字符串数据类型(显示给用户看)

    time。strftime(字符串格式实际)

    import time
    fm1 = time.strftime('%Y-%m-%d')     # 年月日 2018-09-04
    fm2 = time.strftime('%H:%M:%S')     # 时分秒 15:48:25
    fm3 = time.strftime('%c')           # 外国格式 ue Sep  4 15:48:25 2018
    fm4 = time.strftime('%X')           # 时分秒 15:48:25
    fm5 = time.strftime('%x')           # 月/日/年 09/04/18

     

    ③ 结构化时间: 元组格式,用于时间戳时间和格式化时间之间的转化

    time.localtime()

    import time
    t = time.localtime()
    print(t)
    
    '''
    time.struct_time(tm_year=2018, tm_mon=9, tm_mday=4, tm_hour=15, tm_min=52, tm_sec=5, tm_wday=1, tm_yday=247, tm_isdst=0)
    '''

     

    时间格式的转化:

     

    格式化时间 ---> 时间戳时间

    fmt = time.strftime('%x %X')       # 格式化时间
    stt = time.strptime(fmt,'%x %X')   # 结构化时间
    t = time.mktime(stt)               # 时间戳时间
    print(fmt)
    print(stt)
    print(t)
    
    '''
    09/04/18 15:56:53
    time.struct_time(tm_year=2018, tm_mon=9, tm_mday=4, tm_hour=15, tm_min=56, tm_sec=53, tm_wday=1, tm_yday=247, tm_isdst=-1)
    1536047813.0
    '''

     

    时间戳时间 ---> 格式化时间

    t = time.time()                             # 时间戳时间
    stt = time.localtime(t)                     # 结构化时间
    fmt = time.strftime('%Y-%m-%d %X',stt)      # 格式化时间
    print(t)
    print(stt)
    print(fmt)
    
    '''
    1536048042.169353
    time.struct_time(tm_year=2018, tm_mon=9, tm_mday=4, tm_hour=16, tm_min=0, tm_sec=42, tm_wday=1, tm_yday=247, tm_isdst=0)
    2018-09-04 16:00:42
    '''

     

     

    结构化时间 --> %a %b %d %H:%M:%S %Y串

    t = time.asctime()                              # 结构化时间 %a %b %d %H:%M:%S %Y串
    t1 = time.asctime(time.localtime(2000000000))   # 结构化时间 %a %b %d %H:%M:%S %Y串
    print(t)                    # Tue Sep  4 16:04:17 2018
    print(t1)                   # Wed May 18 11:33:20 2033

     

    时间戳 --> %a %b %d %H:%M:%S %Y串

    t = time.ctime()
    t2 = time.ctime(2000000000)
    print(t)                        # Tue Sep  4 16:06:32 2018
    print(t2)                       # Wed May 18 11:33:20 2033

     

    四、随机数模块

    随机小数(一般用于科学计算)

    random.random()    0-1之间的小数(0,1)

    import random
    r = random.random()               # 0-1之间的小数
    print(r)
    print(round(r,2))                 # 保留两位小数
    
    '''
    0.13465619587224942
    0.13
    '''

     

    random.uniform(a,b)  a-b之间的小数 (a,b)

    r1 = random.uniform(10,100)         # 10-100之间的小数
    r2 = random.uniform(100,10)         # 10-100之间的小数
    print(r1)
    print(r2)
    
    '''
    66.24475927171648
    31.986449179748902
    '''

     

    随机整数

    random.randint(a,b)  a-b之间的整数 [a,b]

    r1 = random.randint(5,10)           # 5-10之间的整数 [5-10]
    print(r1)                           # 5

     

    random.randrange(a,b)      a-b之间的整数[a,b)

    r1 = random.randrange(1,100)          # 1-100之间的整数 [1,100)
    print(r1)                             # 88

     

    random.randrange(a,b,c)   a-b步长为c的整数 [a,b)

    r1 = random.randrange(0,100,2)          # 0-100之间的偶数的随机数,[0,100)
    print(r1)                               # 52

     

    列表中的随机元素

    random.choice(list/tuple/range/str)       从列表总随机抽取一个元素

    lis = ['a','b','c',1,2,3]
    r1 = random.choice(lis)             # 从列表中随机一个元素
    print(r1)                           # 3

     

    random.sample(list,n)    从列表中随机抽取n个元素,组成列表

    lis = ['a','b','c',1,2,3]
    r = random.sample(lis,2)            # 从列表中随机2个元素组成列表
    print(r)                            # ['a', 'c']

     

    列表的乱序排列(在原列表的上修改)

    random.shuffle(list)     在原列表的基础上打乱列表元素,节省内存

    lis = ['a','b','c',1,2,3]
    random.shuffle(lis)                 # 打乱列表的元素
    print(lis)                          # [3, 2, 1, 'b', 'c', 'a']

     

    验证码

    import random
    def verification_code(n=6,letter_flag = True):
        code = ''
        for i in range(n):
            c = str(random.randint(0,9))      # 0-9整数的随机数
            if letter_flag:                   # letter_flag随机字母
                cap = chr(random.randint(65,90))    # A-Z的随机字母,通过chr转化为字母
                low = chr(random.randint(97,122))   # a-z的随机字母,通过chr转化为字母
                c = random.choice([c,cap,low])
            code += c
        return code

     

    五、OS模块

    __file__  当前文件位置

    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.system("bash command") 运行shell命令,直接显示
    os.popen("bash command).read() 运行shell命令,获取执行结果
    os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
    os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
    
    
    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的大小
    stat 结构:
    
    st_mode: inode 保护模式
    st_ino: inode 节点号。
    st_dev: inode 驻留的设备。
    st_nlink: inode 的链接数。
    st_uid: 所有者的用户ID。
    st_gid: 所有者的组ID。
    st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
    st_atime: 上次访问的时间。
    st_mtime: 最后一次修改的时间。
    st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。
    os模块的属性
    
    os.sep    输出操作系统特定的路径分隔符,win下为"\",Linux下为"/"
    os.linesep    输出当前平台使用的行终止符,win下为"
    ",Linux下为"
    "
    os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
    os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'

     

    六、sys模块

    sys.path   一个模块能否被导入,就看这个模块所在的目录在不在sys.path路径中,import某个模块会从头到尾取找某个模块,找到就返回

    内置模块在python/lib,第三方模块在/venv/lib/site-pakcages

    内置模块和第三方扩展模块都不需要处理,sys.path就可以直接调用

    自定义模块的导入工作需要手动修改sys.path,当前文件夹的首个位置

    sys.argv 执行py文件的时候传入的参数
    sys.path 查看模块搜索路径 import 模块的时候从这个路径下来寻找
    sys.modules 查看当前导入的模块和它的命名空间

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

    七、collection 模块

    collection 根据基础数据类型做了一些扩展:

    ① Counter

    ② 有序字典

    ③ 默认字典

    ④ 可命名元组

    ⑤ 双端队列

     

    Counter

    Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。

    from collections import Counter
    c = Counter('abcabcde')         # 可传入可迭代对象来创建(list、tuple、dict、str等)
    print(c)                        # Counter({'a': 2, 'b': 2, 'c': 2, 'd': 1, 'e': 1})
    
    print(c['z'])                   # 访问的键不存在,返回0

     

    计数器的更新(增加和减少)

    from collections import Counter
    c = Counter('hello')
    c.update('hello')                  # 计算器的更新:增加
    print(c)                           # Counter({'l': 4, 'h': 2, 'e': 2, 'o': 2})
    c.subtract('hello')                # 计算器的更新:减少
    print(c)                           # Counter({'l': 2, 'h': 1, 'e': 1, 'o': 1})

     

    常用操作:

    elements()      # 返回一个迭代器。元素被重复了多少次,在该迭代器中就包含多少个该元素。元素排列无确定顺序,个数小于1的元素不被包含。
    sum(c.values())  # 所有计数的总数
    c.clear()  # 重置Counter对象,注意不是删除
    list(c)  # 将c中的键转为列表
    set(c)  # 将c中的键转为set
    dict(c)  # 将c中的键值对转为字典
    c.items()  # 转为(elem, cnt)格式的列表
    Counter(dict(list_of_pairs))  # 从(elem, cnt)格式的列表转换为Counter类对象
    c.most_common()[:-n:-1]  # 取出计数最少的n-1个元素
    c += Counter()  # 移除0和负值
    del c['a']      # 删除键值对

     

     

    OrderedDict 有序字典,python3.6版本以后的字典是有序的

    from collections import OrderedDict
    dic = OrderedDict([('a',1),('b',2)])     # OrderedDict 的创建
    print(dic)                  # OrderedDict([('a', 1), ('b', 2)])

    defaultdict  默认字典

    defaultdict类的初始化函数接受一个类型作为参数,当所访问的键不存在的时候,可以实例化一个值作为默认值

    from collections import defaultdict
    func = lambda :'default'
    l = defaultdict(func)
    print(l['a'])       # 不存在该键,会返回默认值
    l['a'] = 1
    print(l)
    
    '''
    default
    defaultdict(<function <lambda> at 0x0000027577BE2E18>, {'a': 1})

    namedtuple  可命名元组

    语法:namedtuple(类名,[对象属性])

    使用场景:元组的元素都有固定的意义,就用可命名元组,非常类似一个只有属性没有属性的类。

    只有属性没有方法,当定义一个类,属性是不变的,没有方法,就可以使用可命名元组

    特点:

    a.元组的是不可变的,元素不能修改

    b.元组要描述很多值,用户能直观地看到

    c.和元组没有交集,不能通过索引访问,只能通过属性访问

    d.一旦实例化就不能修改属性的值

    from collections import namedtuple
    today = namedtuple('Date_today',['year','month','day'])
    d = today(2018,9,5)
    print(d.year)           # 2018
    print(d.month)          # 9
    print(d.day)            # 5
    print(type(d))          # <class '__main__.Date_today'>

    数据类型:队列

    队列是一种数据类型,python里存在于模块,导入queue模块才能使用

    队列的特性是先进先出,类似与买车票,队列能管理程序

    所有的数据类型都能使用方法put()

    import queue
    q = queue.Queue()

    queue.queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。

    |queue.Queue|先进先出队列|
    |queue.LifoQueue|后进先出队列|
    |queue.PriorityQueue|优先级队列|
    |queue.deque|双线队列|

    get()    # 将值放入队列中

    put()    # 将值从队列中取出

    import queue
    q = queue.Queue()
    q.get(1)            # 将一个值放入队列中
    print(q.put(1))     # 将一个值从队列中取出

    其他方法:

    q.qsize() 返回队列的大小
    q.empty() 如果队列为空,返回True,反之False
    q.full() 如果队列满了,返回True,反之False
    q.full 与 maxsize 大小对应
    q.get([block[, timeout]]) 获取队列,timeout等待时间
    q.get_nowait() 相当q.get(False)
    非阻塞 q.put(item) 写入队列,timeout等待时间
    q.put_nowait(item) 相当q.put(item, False)
    q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
    q.join() 实际上意味着等到队列为空,再执行别的操作

    deque 双端队列(效率比列表快)

    列表insert插入操作是将所有的元素往后移,效率比较慢,所以列表不能使用insert的方法

    双端队列的数据结构是链表

    双端列表的操作方法跟列表相似

    增加方法:

    from collections import deque
    d = deque()
    d.append(1)
    d.append(2)
    d.appendleft(3)
    print(d)            # deque([3, 1, 2])

    其他的方法:

    clear(清空队列)

    copy(浅拷贝)

    count(返回指定元素的出现次数)

    extend(从队列右边扩展一个列表的元素)

    extendleft(从队列左边扩展一个列表的元素)

    index(查找某个元素的索引位置)

    insert(在指定位置插入元素)---> 效率比列表高1000倍

    pop(获取最右边一个元素,并在队列中删除)

    popleft(获取最左边一个元素,并在队列中删除)

    remove(删除指定元素)

    reverse(队列反转)

    rotate(把右边元素放到左边)

    八、hashllib 模块

    这是一个内部有不止一种算法的模块。

    由于数据的不安全性,为了保证用户的信息的绝对安全,所以的密码都不能以明文的形式存储,而是使用密文的形式存储,这时可使用这个模块。

    模块里的算法都是摘要算法,该算法有特下特点:

    ① 算法不可逆,即密文不能反推明文

    ② 不同的字符串通过这个算法计算的密文总是不同的

    ③ 相同的算法,相同的字符串,获得的结果总是相同

    ④ 不同的语言,不同的环境都能通用

    该模块应用场景:

    ① 登陆验证

    ② 文件的一致性校验

    模块里最常用的算法:

    ① MD5算法

    ② sha算法

    MD5 算法

    步骤:

    ① 必须初始化对象

    ② update() 将字符串转化为密文,该方法接收的只能是bytes类型

    ③ 通过hexdigest() 方法获得结果

    import hashlib
    md5_obj = hashlib.md5()         # 初始化对象
    md5_obj.update('abcde'.encode('utf-8'))     # 只能接收bytes类型,转化为密文
    ret = md5_obj.hexdigest()                 # 获取转化后的密文
    print(ret)                      # b56b4d92b40713acc5af89985d4b786

    登陆验证

    import hashlib
    def login(user,pwd):
        md5 = hashlib.md5() 
        md5.update(pwd)         # 将传入的密码转化为密文
        pwd = md5.hexdigest()
        with open('userinfo',encoding='utf-8') as f:
            for line in f:
                username,password = line.strip().split(',') 
                if user == username and pwd == password:
                    return True
            else:
                return False

    MD5算法的总结:

    ① 目前应用最广的字啊要算法,效率高,相对于SHA算法不复杂,如果只是传统的摘要不安全。

    ② 只要字符串不变,无论update多少次,结果都是一样的

    ③ 对象只能计算一次值,想再用MD5算法的方法,就需要重新实例化对象

    ④ 加密后的结果是一个32位16进制的字符串

    import hashlib
    md5_obj1 = hashlib.md5()
    md5_obj1.update('mypassword'.encode('utf-8'))
    ret1 = md5_obj1.hexdigest()
    
    md5_obj2 = hashlib.md5()
    md5_obj2.update('my'.encode('utf-8'))
    md5_obj2.update('password'.encode('utf-8'))
    ret2 = md5_obj2.hexdigest()
    
    print(ret1 == ret2)         # True

    SHA1 算法

    使用方式和MD5一致,加密后的结果是一个40位16进制的字符串。

    SHA 还有其他算法,SHA 后面的数字越大算法越复杂,但是耗时越久,结果越长,同时安全性越高。

    步骤:

    ① 必须初始化对象

    ② update() 将字符串转化为密文,该方法接收的只能是bytes类型

    ③ 通过hexdigest() 方法获得结果

    import hashlib
    sha_obj = hashlib.sha1()
    sha_obj.update('abced'.encode('utf-8'))  # 只接收bytes类型,转化为密文
    ret = sha_obj.hexdigest()                # 40位十六进制的字符串
    print(ret)                  # bc748caecb1333dca5cecfdbc5b19833f5e1374a

    传统的摘要算法存在的问题:撞库(通过密文表对照推测结果)

    解决撞库的方案:加盐(加强安全性)

    import hashlib
    # 加盐
    md5_obj1 = hashlib.md5('hello'.encode('utf-8'))     # 加盐
    md5_obj1.update('mypassword'.encode('utf-8'))
    ret1 = md5_obj1.hexdigest()
    
    # 传统摘要
    md5_obj2 = hashlib.md5()
    md5_obj2.update('mypassword'.encode('utf-8'))
    ret2 = md5_obj2.hexdigest()
    
    print(ret1,ret2)
    # ret1 = 9402bc9c2e3e5cacced33cd10bc8f769
    # ret2 = 34819d7beeabb9260a5c854bc85b3e44

    但仍然不是绝对的安全,可能被恶意注册来获得密文表来对照推测结果和加盐方式,因此我们使用动态加盐

    动态加盐即通过用户名在作为盐,一般情况用户名是唯一的,就算密码相同,密文也不一样。

    # 动态加盐
    import hashlib
    def login(user,pwd):
        md5 = hashlib.md5(user.encode('utf-8'))     # 动态加盐
        md5.update(pwd)
        pwd = md5.hexdigest()
    
        with open('userinfo',encoding='utf-8') as f:
            for line in f:
                username,password = line.strip().split(',')
                if user == username and pwd == password:
                    return True
            else:
                return False

    文件的一致性校验

    给一个文件总的所有内容进行摘要算法,得到一个MD5值

    大文件应该改以rb的形式来读,读出来的是bytes,不用编码。但是不能按行读,也不能一次性读出来,可以使用read(n)的方式来读取

    import os,hashlib
    def get_md5(path,buffer = 1024):
        if os.path.exists(path):        # 判断文件是否存在
            path = os.path.abspath(path)    # 转化为绝对路径
            if os.path.isfile(path):        # 判断是否文件
                md5 = hashlib.md5()         # 初始化md5对象
                size = os.path.getsize(path)    # 获得文件的大小
                with open(path,'rb') as f:
                    while size:
                        r = f.read(buffer)    # 一次读n个字节
                        size -= len(r)
                        md5.update(r)           # 转化为密文
                return md5.hexdigest()          # 返回MD5值

    九、configparser 模块

    configparser模块是用来解析ini配置文件的解析器

    ini文件结构需要注意一下几点:

    键值对可用=或者:进行分隔
    section的名字是区分大小写的,而key的名字是不区分大小写的
    键值对中头部和尾部的空白符会被去掉
    值可以为多行
    配置文件可以包含注释,注释以#或者;为前缀
    注意:configparser有default_section的概念,默认为[DEFAULT]节,也就是之后的所有的section都有该默认section中的键值对

    ConfigParser模块以ConfigParser类为例,其操作基本分为三类:1)初始化;2)读取配置;3)写入配置。

    1. ConfigParser 初始化

    使用ConfigParser 首选需要初始化实例,并读取配置文件:

    cf = ConfigParser.ConfigParser() cf.read("配置文件名")

    2. 基本的读取配置文件

    -read(filename) 直接读取ini文件内容

    -sections() 得到所有的section,并以列表的形式返回

    -options(section) 得到该section的所有option

    -items(section) 得到该section的所有键值对

    -get(section,option) 得到section中option的值,返回为string类型

    -getint(section,option) 得到section中option的值,返回为int类型,还有相应的getboolean()和getfloat() 函数。

     

    3.基本的写入配置文件

    -add_section(section) 添加一个新的section

    -set( section, option, value) 对section中的option进行设置,需要调用write将内容写入配置文件。

    十、logging 模块

     日志的分级记录:

      debug:   计算或工作的细节

      info:       记录用户的增删改查操作

      warning    警告操作

      error       错误操作

      critical     批判的错误,直接导致程序出错或退出

    简单配置:

    不能写中文,但不用创建对象

    import logging
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(filename)s %(levelname)s %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    
    logging.debug('debug message')
    logging.info('info message')
    logging.warning('warning message')
    logging.error('error message')
    logging.critical('critical message')
    
    '''
    2018-09-06 17:24:11 exercise.py DEBUG debug message
    2018-09-06 17:24:11 exercise.py INFO info message
    2018-09-06 17:24:11 exercise.py WARNING warning message
    2018-09-06 17:24:11 exercise.py ERROR error message
    2018-09-06 17:24:11 exercise.py CRITICAL critical message
    '''

    了解一下 basicConfig 的参数都有哪些:

    • filename:即日志输出的文件名,如果指定了这个信息之后,实际上会启用 FileHandler,而不再是 StreamHandler,这样日志信息便会输出到文件中了。
    • filemode:这个是指定日志文件的写入方式,有两种形式,一种是 w,一种是 a,分别代表清除后写入和追加写入。
    • format:指定日志信息的输出格式,即上文示例所示的参数:
      • %(levelno)s:打印日志级别的数值。
      • %(levelname)s:打印日志级别的名称。
      • %(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]。
      • %(filename)s:打印当前执行程序名。
      • %(funcName)s:打印日志的当前函数。
      • %(lineno)d:打印日志的当前行号。
      • %(asctime)s:打印日志的时间。
      • %(thread)d:打印线程ID。
      • %(threadName)s:打印线程名称。
      • %(process)d:打印进程ID。
      • %(processName)s:打印线程名称。
      • %(module)s:打印模块名称。
      • %(message)s:打印日志信息。
    • datefmt:指定时间的输出格式。
    • style:如果 format 参数指定了,这个参数就可以指定格式化时的占位符风格,如 %、{、$ 等。
    • level:指定日志输出的类别,程序会输出大于等于此级别的信息。
    • stream:在没有指定 filename 的时候会默认使用 StreamHandler,这时 stream 可以指定初始化的文件流。
    • handlers:可以指定日志处理时所使用的 Handlers,必须是可迭代的。

    对象的配置

    ① 可以写入多个文件,正常情况下只写一个

    ② 解决中文的问题

    ③ 同时向文件和屏幕输出内容

    创建步骤:

    ① 先创建对象log对象,logger

    ② 创建一个控制文件输出的文件句柄

    ③ 创建控制屏幕输出的屏幕操作符

    ④ 创建一个格式

    ⑤ 文件句柄绑定一个格式

    ⑥ 屏幕操作符绑定一个格式

    ⑦ logger对象绑定文件句柄和屏幕操作符

    import logging
    logger = logging.getLogger()        # 创建logging的对象
    logger.setLevel(logging.DEBUG)      # 设置告警等级DEBUG及以上告警
    fh = logging.FileHandler('procedure.log',encoding='utf-8')   # 创建文件输出的文件操作符
    sh = logging.StreamHandler()        # 创建控制屏幕输出的屏幕操作符
    fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                            datefmt='%Y-%m-%d %H:%M:%S')    # 创建格式
    
    fh.setFormatter(fmt)                # 文件操作符绑定格式
    sh.setFormatter(fmt)                # 屏幕操作符绑定格式
    sh.setLevel(logging.ERROR)        # 设置屏幕输出的告警等级
    logger.addHandler(sh)               # 对象绑定屏幕控制符
    logger.addHandler(fh)               # 对象绑定文件操作符
    
    logging.debug('debug message')
    logging.info('info message')
    logging.warning('warning message')
    logging.error('error message')
    logging.critical('critical message')
    
    '''
    2018-09-06 17:34:49 - root - ERROR - error message
    2018-09-06 17:34:49 - root - CRITICAL - critical message
    '''

    参考文档:https://cuiqingcai.com/6080.html

           https://www.cnblogs.com/yyds/p/6901864.html

  • 相关阅读:
    Unity Notes调制粒子系统的颗粒的最大数目
    Swift编程语言学习2.1——基础运营商(在)
    JavaScript语言基础知识6
    算法题:合并两个有序列表
    DDFT
    Java For循环效率试验
    Delphi ORD
    Delphi TcxTreeList 节点添加图片
    SQL Server 除法 不起作用的问题
    Delphi 继承基类的窗体,并显示基类的控件操作。
  • 原文地址:https://www.cnblogs.com/st-st/p/9581447.html
Copyright © 2011-2022 走看看