zoukankan      html  css  js  c++  java
  • [ 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 模块实现思路是最简单的。

  • 相关阅读:
    mac上python3安装HTMLTestRunner
    双目深度估计传统算法流程及OpenCV的编译注意事项
    深度学习梯度反向传播出现Nan值的原因归类
    1394. Find Lucky Integer in an Array
    1399. Count Largest Group
    1200. Minimum Absolute Difference
    999. Available Captures for Rook
    509. Fibonacci Number
    1160. Find Words That Can Be Formed by Characters
    1122. Relative Sort Array
  • 原文地址:https://www.cnblogs.com/hukey/p/9791182.html
Copyright © 2011-2022 走看看