Python3 对象序列化 - pickle 模块

yufei       6 年, 2 月 前       2165

Python 中的 pickle 模块是实现了二进制协议的,用于序列化和反序列化一个 Python 对象结构。

Pickling : 这是一个将 Python 对象层次结构转换为字节流的过程

Unpickling : 它是 Pickling 过程的逆过程,将字节流被转换为 Python 对象层次结构。

pickle 模块提供的序列化和反序列化接口

pickle 模块提供了两个主要的方法用于序列化和反序列化 Python 对象。

方法 说明
dumps() 该方法用于序列化一个 Python 对象层次结构为二进制字节流
loads() 该方法用于反序列化一个数据流为 Python 对象层次结构

为了更好的控制序列化和反序列化,这两个方法会分别创建 PicklerUnpickler 对象。

pickle 模块提供的常量

pickle 模块提供了两个常量

常量 说明
pickle.HIGHEST_PROTOCOL 这是一个整数值,表示可用的最高协议版本。它可以作为协议版本的参数传递给 dump()dumps() 函数
pickle.DEFAULT_PROTOCOL 这是一个整数值,表示用于 pickling 的默认协议,其值可能小于最高协议的值

pickle 模块提供的方法

  1. pickle.dump() 方法

    pickle.dump() 方法用于将一个 Python 对象层次结构序列化为二进制字节流。

    该方法的原型如下

    pickle.dump(obj, file, protocol = None, *, fix_imports = True)
    

    此函数等效于 Pickler(file,protocol.dump(obj) ,用于将 obj 序列化并将结果写入到 file 文件对象。

    可选的 protocol 参数是一个整数,用于指定序列化过程时使用的协议版本号。支持的协议范围为 0HIGHEST_PROTOCOL。如果未指定该参数,则默认为 DEFAULT_PROTOCOL。如果指定了负数,则会自动设置为HIGHEST_PROTOCOL

    如果 fix_imports 参数设置为 trueprotocol 小于 3,则序列化时将尝试将新的 Python3 名称映射到 Python2 中使用的旧模块名称,以便使用 Python2 可读取序列化后的数据流。

    我们写一段代码演示下 pickle.dump() 方法的使用

    import pickle 
    import io
    
    class SimpleObject(object):
    
        def __init__(self, name): 
            self.name = name 
            l = list(name) 
            l.reverse() 
            self.name_backwards = ''.join(l) 
            return
    
    data = [] 
    data.append(SimpleObject('pickle')) 
    data.append(SimpleObject('cPickle')) 
    data.append(SimpleObject('last'))
    
    # 使用 BytesIO 模拟一个文件
    out_s = io.BytesIO()
    
    # 将数据写入到流 
    for o in data: 
        print('WRITING: %s (%s)' % (o.name, o.name_backwards))
        pickle.dump(o, out_s) 
        out_s.flush()
    

    运行结果如下

    [yufei@www.twle.cn java]$ python3 demo.py
    WRITING: pickle (elkcip)
    WRITING: cPickle (elkciPc)
    WRITING: last (tsal)
    
  2. pickle.dumps() 方法

    pickle.dumps() 方法用于将一个 Python 对象层次结构序列化为二进制字节流并返回序列化后的结果。

    该方法的原型如下

    pickle.dumps(obj, protocol = None, *, fix_imports = True)
    

    从方法原型中可以看出,参数和 pickle.dump() 方法几乎一样,因此我们就不做过多解释了。直接上范例

    import pickle
    
    data = [ { 'a':'A', 'b':2, 'c':3.0 } ] 
    data_string = pickle.dumps(data) 
    print ('PICKLE:', data_string)
    

    运行结果如下

    [yufei@www.twle.cn java]$ python3 demo.py
    PICKLE: b'\x80\x03]q\x00}q\x01(X\x01\x00\x00\x00aq\x02X\x01\x00\x00\x00Aq\x03X\x01\x00\x00\x00bq\x04K\x02X\x01\x00\x00\x00cq\x05G@\x08\x00\x00\x00\x00\x00\x00ua.
    
  3. pickle.load() 方法

    pickle.load() 方法用于从打开的文件对象文件中读取 pickle 序列化后的二进制数据流,并反序列化为一个 Python 3 对象层次结构

    该方法的原型如下

    pickle.load(file, *, fix_imports = True, encoding = "ASCII", errors = "strict")
    

    该方法和 Unpickler(file).load() 方法是等价的。

    同样的,参数也简单明了,我们不做过多介绍,直接看范例就好

    import pickle 
    import io
    
    class SimpleObject(object):
    
        def __init__(self, name): 
            self.name = name 
            l = list(name) 
            l.reverse() 
            self.name_backwards = ''.join(l) 
            return
    
    data = [] 
    data.append(SimpleObject('pickle')) 
    data.append(SimpleObject('cPickle')) 
    data.append(SimpleObject('last'))
    
    out_s = io.BytesIO()
    
    # Write to the stream 
    for o in data: 
        print('WRITING: %s (%s)' % (o.name, o.name_backwards)) 
        pickle.dump(o, out_s) 
        out_s.flush()
    
    # Set up a read-able stream 
    in_s = io.BytesIO(out_s.getvalue())
    
    # Read the data 
    while True: 
        try: 
            o = pickle.load(in_s) 
        except EOFError: 
            break
        else: 
            print('READ: %s (%s)' % (o.name, o.name_backwards))
    

    运行结果如下

    [yufei@www.twle.cn java]$ python3 demo.py
    WRITING: pickle (elkcip)
    WRITING: cPickle (elkciPc)
    WRITING: last (tsal)
    READ: pickle (elkcip)
    READ: cPickle (elkciPc)
    READ: last (tsal)
    
  4. pickle.loads() 方法

    pickle.loads() 方法用于从二进制数据流中读取 pickle 序列化后的二进制数据流,并反序列化为一个 Python 3 对象层次结构

    该方法的原型如下

    pickle.loads(bytes_object, *, fix_imports = True, encoding = "ASCII", errors = "strict")
    

    该方法和 pickle.load() 方法类似,区别在于一个从文件对象中读取数据,一个从二进制数据流中读取数据。

    我们写一段代码演示下这个方法的使用

    import pickle 
    import pprint
    
    data1 = [ { 'a':'A', 'b':2, 'c':3.0 } ] 
    print('BEFORE:'), 
    pprint.pprint(data1)
    
    data1_string = pickle.dumps(data1)
    
    data2 = pickle.loads(data1_string) 
    print('AFTER:'), 
    pprint.pprint(data2)
    
    print('SAME?:', (data1 is data2)) 
    print('EQUAL?:', (data1 == data2))
    

    运行结果如下

    [yufei@www.twle.cn java]$ python3 demo.py
    BEFORE:
    [{'a': 'A', 'b': 2, 'c': 3.0}]
    AFTER:
    [{'a': 'A', 'b': 2, 'c': 3.0}]
    SAME?: False
    EQUAL?: True
    
目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.