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

文章目录

  • 玩转序列化,用这个库就对了:Python的pickle库
  • 背景
  • 什么是pickle库?
  • 如何安装这个库?
  • 5个简单的库函数使用方法
  • dump函数
  • load函数
  • dumps函数
  • loads函数
  • 高级用法:使用协议
  • 5个场景使用代码说明
  • 场景1:保存和加载自定义类实例
  • 场景2:保存和加载复杂数据结构
  • 场景3:跨网络传输Python对象
  • 场景4:多进程中使用pickle
  • 场景5:使用pickle进行深拷贝
  • 常见3个bug以及解决方案
  • Bug1:尝试序列化不支持的对象
  • Bug2:使用旧版本的pickle库打开新版本序列化的数据
  • Bug3:在不同Python版本间序列化和反序列化
  • 总结

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

    背景

    在Python编程中,我们经常需要将对象转换成字节流以便存储或传输。这个过程被称为序列化。序列化是将数据结构或对象状态转换成可存储或可传输的形式的过程。而反序列化则是相反的过程,即将字节流转换回原始的数据结构或对象。Python标准库中的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)
    
  • 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)
    
  • 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\x02e.'
    data = pickle.loads(serialized_data)
    print(data)
    
  • data = pickle.loads(serialized_data):从字节流中反序列化成Python对象。
  • 高级用法:使用协议

    pickle支持不同的序列化协议,可以通过protocol参数指定。

    import pickle
    
    data = {'key': 'value'}
    with open('data.pkl', 'wb') as f:
        pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL)
    
  • pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL):使用最高版本的协议序列化对象。
  • 5个场景使用代码说明

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

    import pickle
    
    class MyClass:
        def __init__(self, name):
            self.name = name
    
    # 创建实例
    my_object = MyClass("Kimi")
    
    # 序列化
    with open('my_object.pkl', 'wb') as f:
        pickle.dump(my_object, f)
    
    # 反序列化
    with open('my_object.pkl', 'rb') as f:
        loaded_object = pickle.load(f)
    print(loaded_object.name)
    

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

    import pickle
    
    data = {'list': [1, 2, 3], 'dict': {'a': 1, 'b': 2}, 'tuple': (1, 2)}
    
    # 序列化
    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)
    

    场景3:跨网络传输Python对象

    import pickle
    import socket
    
    # 创建一个socket对象
    s = socket.socket()
    s.connect(('example.com', 12345))
    
    # 序列化对象
    data = {'key': 'value'}
    serialized_data = pickle.dumps(data)
    
    # 发送数据
    s.sendall(serialized_data)
    
    # 关闭连接
    s.close()
    

    场景4:多进程中使用pickle

    import pickle
    from multiprocessing import Process, Pipe
    
    def worker(conn):
        conn.send(pickle.loads(conn.recv()))
        conn.close()
    
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe()
        p = Process(target=worker, args=(child_conn,))
        p.start()
        parent_conn.send(pickle.dumps({'key': 'value'}))
        print(parent_conn.recv())
        p.join()
    

    场景5:使用pickle进行深拷贝

    import pickle
    
    data = {'key': 'value'}
    
    # 深拷贝
    copied_data = pickle.loads(pickle.dumps(data))
    print(copied_data is data)  # False,证明是深拷贝
    

    常见3个bug以及解决方案

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

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

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

    import pickle
    
    class MyClass:
        def __init__(self, name):
            self.name = name
    
    # 正确的序列化方式
    my_object = MyClass("Kimi")
    with open('my_object.pkl', 'wb') as f:
        pickle.dump(my_object, f)
    

    Bug2:使用旧版本的pickle库打开新版本序列化的数据

    错误信息pickle.UnpicklingError: invalid load key, bytes le

    解决方案
    确保使用相同版本的pickle库进行序列化和反序列化。

    import pickle
    
    # 序列化
    data = {'key': 'value'}
    with open('data.pkl', 'wb') as f:
        pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL)
    
    # 反序列化
    with open('data.pkl', 'rb') as f:
        data = pickle.load(f)
    

    Bug3:在不同Python版本间序列化和反序列化

    错误信息pickle.UnpicklingError: bad byte load key

    解决方案
    在不同Python版本间序列化和反序列化时,使用兼容的协议版本。

    import pickle
    
    # 序列化
    data = {'key': 'value'}
    with open('data.pkl', 'wb') as f:
        pickle.dump(data, f, protocol=pickle.DEFAULT_PROTOCOL)
    
    # 反序列化
    with open('data.pkl', 'rb') as f:
        data = pickle.load(f)
    

    总结

    pickle库是Python中一个强大而灵活的序列化工具,它能够处理各种复杂的数据结构,并且易于使用。通过本文的介绍,你应该能够掌握pickle的基本用法,以及如何在实际场景中应用它。记住,虽然pickle非常方便,但由于其安全性问题,不建议用于序列化不可信的数据。对于需要高安全性的场景,可以考虑使用其他序列化库,如jsonxml

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

    作者:正东AI

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

    发表回复