玩转序列化,用这个库就对了:Python的pickle库详解

文章目录

  • 玩转序列化,用这个库就对了:Python的pickle库详解
  • 背景
  • 这个库是什么?
  • 如何安装这个库?
  • 5个简单的库函数使用方法
  • dump函数
  • load函数
  • dumps函数
  • loads函数
  • 高级序列化设置
  • 5个场景使用代码说明
  • 场景1:保存和加载自定义类实例
  • 场景2:保存和加载复杂数据结构
  • 场景3:在多进程中使用pickle传递数据
  • 场景4:使用pickle进行网络通信
  • 场景5:使用pickle进行错误跟踪
  • 常见3个bug以及解决方案
  • Bug1:尝试序列化不支持的对象
  • Bug2:反序列化时文件损坏
  • Bug3:跨Python版本序列化问题
  • 总结

  • 玩转序列化,用这个库就对了:Python的pickle库详解

    背景

    在Python编程中,我们经常需要将对象的状态保存到文件中,以便在程序重启后能够恢复这些对象。这就是所谓的序列化(Serialization)。序列化是将数据结构或对象状态转换成可存储或可传输的格式的过程。Python提供了一个内置的库pickle,专门用于对象的序列化和反序列化。通过pickle,我们可以轻松地将Python对象转换为字节流,并在需要时将这些字节流恢复为原始对象。接下来,我们将深入了解pickle库的魔力。

    这个库是什么?

    pickle是Python的一个标准库,用于序列化和反序列化Python对象结构。它能够将Python对象编码成字节流,以便存储在文件中或通过网络传输,之后又能够将这些字节流解码回原始的Python对象。

    如何安装这个库?

    由于pickle是Python的标准库,因此无需额外安装。只需在Python脚本中导入即可使用。

    import pickle
    

    5个简单的库函数使用方法

    dump函数

    将Python对象序列化并写入文件。

    import pickle
    
    data = {'key': 'value'}
    with open('data.pkl', 'wb') as f:
        pickle.dump(data, f)
    
  • import pickle:导入pickle模块。
  • data = {'key': 'value'}:创建一个字典对象。
  • with open('data.pkl', 'wb') as f:以二进制写入模式打开文件。
  • pickle.dump(data, f):将data对象序列化并写入文件。
  • load函数

    从文件中读取字节流,并反序列化成Python对象。

    import pickle
    
    with open('data.pkl', 'rb') as f:
        data = pickle.load(f)
    print(data)  # 输出:{'key': 'value'}
    
  • with open('data.pkl', 'rb') as f:以二进制读取模式打开文件。
  • data = pickle.load(f):从文件中读取字节流并反序列化成Python对象。
  • dumps函数

    将Python对象序列化成字节流。

    import pickle
    
    data = {'key': 'value'}
    serialized_data = pickle.dumps(data)
    print(serialized_data)  # 输出:b'\x80\x03}q\x00(X\x03\x00\x00\x00keyq\x01X\x05\x00\x00\x00valueq\x02.'
    
  • serialized_data = pickle.dumps(data):将data对象序列化成字节流。
  • loads函数

    从字节流中反序列化出Python对象。

    import pickle
    
    serialized_data = b'\x80\x03}q\x00(X\x03\x00\x00\x00keyq\x01X\x05\x00\x00\x00valueq\x02.'
    data = pickle.loads(serialized_data)
    print(data)  # 输出:{'key': 'value'}
    
  • data = pickle.loads(serialized_data):从字节流中反序列化出Python对象。
  • 高级序列化设置

    使用protocol参数来指定序列化协议版本。

    import pickle
    
    data = {'key': 'value'}
    # 使用最新的协议版本
    serialized_data = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
    
  • pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL):使用最新的协议版本进行序列化。
  • 5个场景使用代码说明

    场景1:保存和加载自定义类实例

    import pickle
    
    class MyClass:
        def __init__(self, name):
            self.name = name
    
    my_obj = MyClass("Kimi")
    with open('my_obj.pkl', 'wb') as f:
        pickle.dump(my_obj, f)
    
    with open('my_obj.pkl', 'rb') as f:
        loaded_obj = pickle.load(f)
    print(loaded_obj.name)  # 输出:Kimi
    

    场景2:保存和加载复杂数据结构

    import pickle
    
    data = {'a': [1, 2.5, 3, 4+4j], 'b': ("string", b'byte string')}
    with open('complex_data.pkl', 'wb') as f:
        pickle.dump(data, f)
    
    with open('complex_data.pkl', 'rb') as f:
        loaded_data = pickle.load(f)
    print(loaded_data)  # 输出:{'a': [1, 2.5, 3, (4+4j)], 'b': ('string', b'byte string')}
    

    场景3:在多进程中使用pickle传递数据

    from multiprocessing import Process, Pipe
    import pickle
    
    def func(conn):
        conn.send(pickle.loads(b'\x80\x03}q\x00(X\x03\x00\x00\x00keyq\x01X\x05\x00\x00\x00valueq\x02.'))
        conn.close()
    
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe()
        p = Process(target=func, args=(child_conn,))
        p.start()
        print(parent_conn.recv())  # 输出:{'key': 'value'}
        p.join()
    

    场景4:使用pickle进行网络通信

    import socket
    import pickle
    
    s = socket.socket()
    s.connect(('example.com', 80))
    data = {'key': 'value'}
    s.sendall(pickle.dumps(data))
    response = s.recv(1024)
    s.close()
    loaded_data = pickle.loads(response)
    print(loaded_data)  # 输出:{'key': 'value'}
    

    场景5:使用pickle进行错误跟踪

    import pickle
    
    try:
        # 模拟错误
        raise ValueError("Something went wrong")
    except ValueError as e:
        with open('error.pkl', 'wb') as f:
            pickle.dump(e, f)
    
    with open('error.pkl', 'rb') as f:
        loaded_error = pickle.load(f)
    print(loaded_error)  # 输出:ValueError('Something went wrong',)
    

    常见3个bug以及解决方案

    Bug1:尝试序列化不支持的对象

    错误信息TypeError: Can't pickle <type>: <attribute>

    解决方案
    确保所有要序列化的对象都是pickle支持的类型。如果需要序列化自定义对象,确保它们是可序列化的。

    import pickle
    
    class MyClass:
        def __init__(self, name):
            self.name = name
    
    my_obj = MyClass("Kimi")
    with open('my_obj.pkl', 'wb') as f:
        pickle.dump(my_obj, f)  # 正确:MyClass实例是可序列化的
    

    Bug2:反序列化时文件损坏

    错误信息EOFErrorpickle.UnpicklingError

    解决方案
    确保序列化和反序列化过程中文件没有被意外修改或损坏。

    import pickle
    
    try:
        with open('corrupted.pkl', 'rb') as f:
            data = pickle.load(f)
    except (EOFError, pickle.UnpicklingError):
        print("文件损坏或不完整")
    

    Bug3:跨Python版本序列化问题

    错误信息pickle.UnpicklingError

    解决方案
    使用兼容的协议版本进行序列化和反序列化。

    import pickle
    
    # 序列化时指定协议版本
    serialized_data = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
    
    # 反序列化时也使用相同的协议版本
    data = pickle.loads(serialized_data)
    

    总结

    pickle库是Python中一个强大而灵活的序列化工具,它允许我们轻松地将Python对象保存到文件中,并在需要时恢复它们。通过本文的介绍,我们了解了pickle的基本用法、常见场景以及可能遇到的问题和解决方案。掌握pickle,将使你在处理对象持久化时更加得心应手。

    如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

    作者:正东AI

    物联沃分享整理
    物联沃-IOTWORD物联网 » 玩转序列化,用这个库就对了:Python的pickle库详解

    发表回复