• [ python ] 序列化模块


    什么叫序列化:
        将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。

    序列化的目的:
        1. 以某种存储形式使自定义对象持久化
        2. 将对象从一个地方传递到另一个地方
        3. 使程序更具维护性

    json 模块

    json模块提供了四个功能:dumps、loads 和 dump、load

    import json
    
    dic = {'k1':1, 'k2': 2, 'k3': 3}
    
    # 序列化
    str_dic = json.dumps(dic)   # dumps 就是将字典类型转换为字符串类型
    print(type(str_dic), str_dic)
    
    # 执行结果:
    # <class 'str'> {"k1": 1, "k2": 2, "k3": 3}
    
    
    # 反序列化
    dic2 = json.loads(str_dic)  # loads 将字符串类型转换为字典类型
    print(type(dic2), dic2)
    
    # 执行结果:
    # <class 'dict'> {'k2': 2, 'k3': 3, 'k1': 1}
    dumps 和 loads

    dumps 和 loads 都是在内存中对数据进行操作,并没有将序列化后的数据保存到硬盘,程序退出,数据消失。如果要将序列化后的数据永久的保存起来,就需要使用 dump 和 load 来操作:

    import json
    
    dic = {'k1':1, 'k2': 2, 'k3': 3}
    with open('test.json', 'w', encoding='utf-8') as f:
        json.dump(dic, f)   # dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
    dump 持久序列化到文件
    with open('test.json', 'r', encoding='utf-8') as f:
        dic = json.load(f)  # load 方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
    
    print(type(dic), dic)
    
    # 执行结果:
    # <class 'dict'> {'k2': 2, 'k3': 3, 'k1': 1}
    load从文件中反序列化

    当序列化中数据含有中文,建议添加ensure_ascii关键字参数来进行序列化,这样在json文件中依然会显示中文

    import json
    dic = {'k1': '中国', 'k2': '美国', 'k3': 3}
    with open('file.json', 'w', encoding='utf-8') as f:
        json.dump(dic, f, ensure_ascii=False)
    ensure_ascii关键字参数

    json的格式化输出:

    import json
    data = {'username':['小明','baby'],'sex':'male','age':16}
    json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False)
    print(json_dic2)
    
    执行结果:
    
    {
      "age":16,
      "sex":"male",
      "username":[
        "小明",
        "baby"
      ]
    }
    json格式化输出

    实例:

    使用 json 模块实现用户注册登录:

    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    # Author: hkey
    import json
    import os
    
    
    def file_oper(file, mode, *args):
        if mode == 'w':
            user_info = args[0]
            with open(file, mode) as f:
                json.dump(user_info, f)
        elif mode == 'r':
            with open(file, mode) as f:
                user_info = json.load(f)
            return user_info
    
    
    def regist(file):
        user_dict = file_oper(file, 'r')
        while True:
            username = input('username:').strip()
            if not username: continue
            if username in user_dict:
                print('33[31;1m错误:用户名已存在.33[0m')
            else:
                break
    
        password = input('password:').strip()
        user_dict[username] = password
        file_oper(file, 'w', user_dict)
        print('33[32;1m注册成功.33[0m')
    
    
    def login(file):
        user_dict = file_oper(file, 'r')
        while True:
            username = input('username:').strip()
            if not username: continue
            if username not in user_dict:
                print('33[32;1m错误:用户名不存在.33[0m')
            else:
                break
        password = input('password:').strip()
        if user_dict[username] == password:
            print('33[32;1m登录成功.33[0m')
        else:
            print('33[31;1m密码错误.33[0m')
    
    
    def showmenu():
        if not os.path.isfile('user_json.db'):
            file_oper('user.db', 'w', {})
        while True:
            print('1. 注册
    '
                  '2. 登录
    '
                  '3. 退出')
            choice = input('>>>').strip()
            if choice == '1':
                regist('user.db')
            elif choice == '2':
                login('user.db')
            elif choice == '3':
                break
            else:
                print('33[31;1m错误:输入错误.33[0m')
    
    
    if __name__ == '__main__':
        showmenu()
    json 用户注册和登录

    pickle 模块

    json模块和pickle模块对比:

    •     json,用于字符串和python部分数据类型间进行转换
    •     pickle,用于python特有的类型和python的数据类型间进行转换

    pickle模块提供了四个功能:dumps、dump(序列化,存储)、loads(反序列化,读)、load(不仅可以序列化字典,列表...可以把python中任意的数据类型序列化)

    pickle模块的使用

    dumps
    import pickle
    
    dic = {'k1': 1, 'k2': 2, 'k3': 3}
    
    str_dic = pickle.dumps(dic) # 使用dumps进行序列化,序列化后是一串字节类型的数据。
    print(str_dic)
    
    # 执行结果:
    # b'x80x03}qx00(Xx02x00x00x00k1qx01Kx01Xx02x00x00x00k2qx02Kx02Xx02x00x00x00k3qx03Kx03u.'
    pickle.dumps序列化
    import pickle
    
    dic2 = pickle.loads(b'x80x03}qx00(Xx02x00x00x00k1qx01Kx01Xx02x00x00x00k2qx02Kx02Xx02x00x00x00k3qx03Kx03u.')
    print(dic2) # loads进行反序列化得到结果
    
    # 执行结果:
    # {'k2': 2, 'k3': 3, 'k1': 1}
    pickle.loads反序列化

    dump 和 load

    import pickle
    l1 = [1, 2, 3, 4, 5, 6, 'hehe', 'haha']
    with open('file.json', 'wb') as f:    # 这里必须使用 'wb'进行写入操作且不用指定字符编码
        pickle.dump(l1, f)
    pickle.dump序列化
    import pickle
    with open('file.json', 'rb') as f:    # 这里必须使用 'rb'进行读取操作且不用指定字符编码
        l2 = pickle.load(f)
    
    print(l2)
    
    # 执行结果:
    # [1, 2, 3, 4, 5, 6, 'hehe', 'haha']
    pickle.load反序列化

    实例:

    使用 pickle 模块实现用户注册登录:

    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    # Author: hkey
    import pickle
    import os
    
    
    def file_oper(file, mode, *args):
        if mode == 'wb':
            user_info = args[0]
            with open(file, mode) as f:
                pickle.dump(user_info, f)
        elif mode == 'rb':
            with open(file, mode) as f:
                user_info = pickle.load(f)
            return user_info
    
    
    def regist(file, user_dict):
        while True:
            username = input('username:').strip()
            if not username: continue
            if username in user_dict:
                print('33[31;1m错误:用户名已存在.33[0m')
            else:
                break
    
        password = input('password:').strip()
        user_dict[username] = password
        file_oper(file, 'wb', user_dict)
        print('33[32;1m注册成功.33[0m')
    
    
    def login(user_dict):
        while True:
            username = input('username:').strip()
            if not username: continue
            if username not in user_dict:
                print('33[32;1m错误:用户名不存在.33[0m')
            else:
                break
        password = input('password:').strip()
        if user_dict[username] == password:
            print('33[32;1m登录成功.33[0m')
        else:
            print('33[31;1m密码错误.33[0m')
    
    
    def showmenu():
        if not os.path.isfile('user.db'):
            file_oper('user.db', 'wb', {})
        user_dict = file_oper('user.db', 'rb')
        while True:
            print('1. 注册
    '
                  '2. 登录
    '
                  '3. 退出')
            choice = input('>>>').strip()
            if choice == '1':
                regist('user.db', user_dict)
            elif choice == '2':
                login(user_dict)
            elif choice == '3':
                break
            else:
                print('33[31;1m错误:输入错误.33[0m')
    
    
    if __name__ == '__main__':
        showmenu()
    pickle 用户注册和登录

    shelve 模块

    shelve是一个简单的数据存储方案,他只有一个函数就是open(),这个函数接收一个参数就是文件名,并且文件名必须是.bat类型的。然后返回一个shelf对象,可以简单的当作一个字典,当你存储完毕的时候,就调用close函数来关闭。

    永久存储数据

    import shelve
    she = shelve.open('user')
    she['xiaom'] = ['male', 20] # 字典的形式,添加一个列表
    she['xiaom'].append('aaa')  # 新增一个元素
    she.close()
    
    -----------------------------------------
    
    import shelve
    s = shelve.open('user')
    print(s['xiaom'])
    s.close()
    
    # 执行结果:
    # ['male', 20]

    在上面的例子中,新增的元素并没有持久保存在文件中。

    这是由于shelve在默认情况下是不会记录持久化对象的任何修改,所以在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。

    回写模式 (writeback=True)

    import shelve
    she = shelve.open('user', writeback=True)   # 开启回写模式
    she['xiaom'] = ['male', 20] # 字典的形式,添加一个列表
    she['xiaom'].append('aaa')  # 新增一个元素
    she.close()
    
    -----------------------------------------
    
    import shelve
    
    s = shelve.open('user')
    print(s['xiaom'])
    s.close()
    
    # 执行结果:
    # ['male', 20, 'aaa']    # 新增或修改的内容持久化成功

    实例:

    使用 shelve 模块实现用户注册登录:

    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    # Author: hkey
    import shelve, hashlib
    
    db = shelve.open('user.db', writeback=True)
    
    
    def regist():
        global db
        while True:
            username = input('username:').strip()
            if not username: continue
            if username in db:
                print('33[31;1m错误:用户名已存在.33[0m')
            else:
                break
        password = input('password:').strip()
        md5 = hashlib.md5()
        md5.update(password.encode())
        password_md5 = md5.hexdigest()
        db[username] = {'password': password_md5}
    
    
    def login():
        global db
        username = input('username:').strip()
        password = input('password:').strip()
        md5 = hashlib.md5()
        md5.update(password.encode())
        password = md5.hexdigest()
        if username in db:
            password_md5 = db[username].get('password')
            if password == password_md5:
                print('33[32;1m登录成功.33[0m')
    
    
    def showmenu():
        global db
        while True:
            print('1. 注册
    '
                  '2. 登录
    '
                  '3. 退出')
            choice = input('>>>').strip()
            if choice == '1':
                regist()
            elif choice == '2':
                login()
            elif choice == '3':
                break
            else:
                print('33[31;1m序号错误.33[0m')
        db.close()
    
    
    if __name__ == '__main__':
        showmenu()
    shelve 用户注册和登录

     json 、 pickle 、 shelve 三个模块使用场景及对比如下:

    1. json在任何编程语言都是通用的格式,因此在多语言编程数据对接使用,但是在python中只有部分数据类型(str、list、dict)能够被序列化;
    2. pickle 是python语言所独有的,能够序列化任何 python 中的数据类型;
    3. shelve 是一个类似dict的对象,更加简单易用。

    在上面三个 用户注册登录 实例中,不难发现使用 shelve 模块实现思路是最简单的。

  • 相关阅读:
    链串
    一个外行谈行业应用的营销问题
    SharePoint 2013的100个新功能之场管理
    Deep Learning and Shallow Learning
    [IOS]UIWebView 请求网络页面或者加载本地资源页面
    九度OJ 打印日期 (模拟)
    STM32学习之路-SysTick的应用(时间延迟)
    box-shadow
    让算法会说话之高速排序
    A5-1和DES两个加密算法的学习
  • 原文地址:https://www.cnblogs.com/hukey/p/9791182.html
Copyright © 2020-2023  润新知