序列化Python对象的方法

问题

你需要将一个Python对象序列化为一个字节流,以便将它保存到一个文件、存储到数据库或者通过网络传输它。

解决方案

对于序列化最普遍的做法就是使用 pickle 模块。为了将一个对象保存到一个文件中,可以这样做:

import pickle

data = ... # Some Python object
f = open('somefile', 'wb')
pickle.dump(data, f)

为了将一个对象转储为一个字符串,可以使用 pickle.dumps()

s = pickle.dumps(data)

为了从字节流中恢复一个对象,使用 pickle.load() pickle.loads() 函数。比如:

# Restore from a file
f = open('somefile', 'rb')
data = pickle.load(f)

# Restore from a string
data = pickle.loads(s)

讨论

对于大多数应用程序来讲,dump() load() 函数的使用就是你有效使用 pickle 模块所需的全部了。 它可适用于绝大部分Python数据类型和用户自定义类的对象实例。 如果你碰到某个库可以让你在数据库中保存/恢复Python对象或者是通过网络传输对象的话, 那么很有可能这个库的底层就使用了 pickle 模块。

pickle 是一种Python特有的自描述的数据编码。 通过自描述,被序列化后的数据包含每个对象开始和结束以及它的类型信息。 因此,你无需担心对象记录的定义,它总是能工作。 举个例子,如果要处理多个对象,你可以这样做:

>>> import pickle
>>> f = open('somedata', 'wb')
>>> pickle.dump([1, 2, 3, 4], f)
>>> pickle.dump('hello', f)
>>> pickle.dump({'Apple', 'Pear', 'Banana'}, f)
>>> f.close()
>>> f = open('somedata', 'rb')
>>> pickle.load(f)
[1, 2, 3, 4]
>>> pickle.load(f)
'hello'
>>> pickle.load(f)
{'Apple', 'Pear', 'Banana'}
>>>

你还能序列化函数,类,还有接口,但是结果数据仅仅将它们的名称编码成对应的代码对象。例如:

>>> import math
>>> import pickle.
>>> pickle.dumps(math.cos)
b'\x80\x03cmath\ncos\nq\x00.'
>>>

当数据反序列化回来的时候,会先假定所有的源数据时可用的。 模块、类和函数会自动按需导入进来。对于Python数据被不同机器上的解析器所共享的应用程序而言, 数据的保存可能会有问题,因为所有的机器都必须访问同一个源代码。

千万不要对不信任的数据使用pickle.load()。
pickle在加载时有一个副作用就是它会自动加载相应模块并构造实例对象。
但是某个坏人如果知道pickle的工作原理,
他就可以创建一个恶意的数据导致Python执行随意指定的系统命令。
因此,一定要保证pickle只在相互之间可以认证对方的解析器的内部使用。

有些类型的对象是不能被序列化的。这些通常是那些依赖外部系统状态的对象, 比如打开的文件,网络连接,线程,进程,栈帧等等。 用户自定义类可以通过提供 __getstate__() __setstate__() 方法来绕过这些限制。 如果定义了这两个方法,pickle.dump() 就会调用 __getstate__() 获取序列化的对象。 类似的,__setstate__() 在反序列化时被调用。为了演示这个工作原理, 下面是一个在内部定义了一个线程但仍然可以序列化和反序列化的类:

# countdown.py
import time
import threading

class Countdown:
  def __init__(self, n):
    self.n = n
    self.thr = threading.Thread(target=self.run)
    self.thr.daemon = True
    self.thr.start()

  def run(self):
    while self.n > 0:
      print('T-minus', self.n)
      self.n -= 1
      time.sleep(5)

  def __getstate__(self):
    return self.n

  def __setstate__(self, n):
    self.__init__(n)

试着运行下面的序列化试验代码:

>>> import countdown
>>> c = countdown.Countdown(30)
>>> T-minus 30
T-minus 29
T-minus 28
...

>>> # After a few moments
>>> f = open('cstate.p', 'wb')
>>> import pickle
>>> pickle.dump(c, f)
>>> f.close()

然后退出Python解析器并重启后再试验下:

>>> f = open('cstate.p', 'rb')
>>> pickle.load(f)
countdown.Countdown object at 0x10069e2d0>
T-minus 19
T-minus 18
...

你可以看到线程又奇迹般的重生了,从你第一次序列化它的地方又恢复过来。

pickle 对于大型的数据结构比如使用 arraynumpy 模块创建的二进制数组效率并不是一个高效的编码方式。 如果你需要移动大量的数组数据,你最好是先在一个文件中将其保存为数组数据块或使用更高级的标准编码方式如HDF5 (需要第三方库的支持)。

由于 pickle 是Python特有的并且附着在源码上,所有如果需要长期存储数据的时候不应该选用它。 例如,如果源码变动了,你所有的存储数据可能会被破坏并且变得不可读取。 坦白来讲,对于在数据库和存档文件中存储数据时,你最好使用更加标准的数据编码格式如XML,CSV或JSON。 这些编码格式更标准,可以被不同的语言支持,并且也能很好的适应源码变更。

最后一点要注意的是 pickle 有大量的配置选项和一些棘手的问题。 对于最常见的使用场景,你不需要去担心这个,但是如果你要在一个重要的程序中使用pickle去做序列化的话, 最好去查阅一下 官方文档

以上就是序列化Python对象的方法的详细内容,更多关于序列化Python对象的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python pickle模块实现对象序列化

    这篇文章主要介绍了Python pickle模块实现对象序列化,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 作用 对Python对象进行序列化,便于存储和传输 Python对象序列化成bytes类型 pickle.dumps(obj) 将Python对象转化为bytes类型 pickle.loads(str) 将转化成的bytes类型数据还原成对象 Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 0

  • Python pickle类库介绍(对象序列化和反序列化)

    一.pickle pickle模块用来实现python对象的序列化和反序列化.通常地pickle将python对象序列化为二进制流或文件.   python对象与文件之间的序列化和反序列化: 复制代码 代码如下: pickle.dump() pickle.load() 如果要实现python对象和字符串间的序列化和反序列化,则使用: 复制代码 代码如下: pickle.dumps() pickle.loads() 可以被序列化的类型有: * None,True 和 False; * 整数,浮点数

  • Python Pickle 实现在同一个文件中序列化多个对象

    也是看别人代码才知道可以打开一个文件就可以把多个对象序列化到这个文件中. with open('../raw_data/remap.pkl', 'wb') as f: pickle.dump(reviews_df, f, pickle.HIGHEST_PROTOCOL) # uid, iid pickle.dump(cate_list, f, pickle.HIGHEST_PROTOCOL) # cid of iid line pickle.dump((user_count, item_coun

  • 在Python中marshal对象序列化的相关知识

    有时候,要把内存中的一个对象持久化保存到磁盘上,或者序列化成二进制流通过网络发送到远程主机上.Python中有很多模块提供了序列化与反序列化的功能,如:marshal, pickle, cPickle等等.今天就讲讲marshal模块. 注意: marshal并不是一个通用的模块,在某些时候它是一个不被推荐使用的模块,因为使用marshal序列化的二进制数据格式还没有文档化,在不同版本的Python中,marshal的实现可能不一样.也就是说,用python2.5序列为一个对象,用python2

  • Python实现JSON反序列化类对象的示例

    我们的网络协议一般是把数据转换成JSON之后再传输.之前在Java里面,实现序列化和反序列化,不管是 jackson ,还是 fastjson 都非常的简单.现在有项目需要用Python来开发,很自然的希望这样的便利也能在Python中体现. 但是在网上看了一些教程,讲反序列化的时候,基本都是转换为 dict 或者 array .这种编程方式我从情感上是无法接受的.难道是这些JSON库都不支持反序列化为类对象?我马上打消了这个念头,Python这样强大的脚本语言,不可能没有完善的JSON库. 于

  • 序列化Python对象的方法

    问题 你需要将一个Python对象序列化为一个字节流,以便将它保存到一个文件.存储到数据库或者通过网络传输它. 解决方案 对于序列化最普遍的做法就是使用 pickle 模块.为了将一个对象保存到一个文件中,可以这样做: import pickle data = ... # Some Python object f = open('somefile', 'wb') pickle.dump(data, f) 为了将一个对象转储为一个字符串,可以使用 pickle.dumps() : s = pick

  • 利用Python命令行传递实例化对象的方法

    一.前言 在开发过程中,遇到了这样一个情况:我们需要在脚本中通过 suprocess.call 方法来启动另外一个脚本(脚本 B),当然啦,还得传递一些参数.在这些参数中,有一个需要传递的是一个实例化后的对象.我们知道,通过命令行的方式传递参数是基于字符格式的,也就是说脚本 B 只能接收到字符串格式的参数,那么如何接收启动脚本传递过来的实例化后的对象呢? 今天就来聊聊我使用的两种笨方法:使用 eval 以及使用 pickle 和 base64 模块. 方法一:使用 eval 其实在代码中使用 e

  • Python 对象序列化与反序列化之pickle json详细解析

    目录 引言 pickle json 尾语 引言 将对象的状态信息转换为可以存储或传输的形式的过程叫作序列化 类似地从序列化后的数据转换成相对应的对象叫作 反序列化 本文介绍 Python 将对象序列化和反序化的两个模块 picklejson pickle pickle # 序列化 In [19]: num = 66 In [20]: s = 'python' In [21]: pi = 3.14 In [22]: li = [1, 2, 3] In [27]: b_num = pickle.du

  • Python对象类型及其运算方法(详解)

    基本要点: 程序中储存的所有数据都是对象(可变对象:值可以修改 不可变对象:值不可修改) 每个对象都有一个身份.一个类型.一个值 例: >>> a1 = 'abc' >>> type(a1) str 创建一个字符串对象,其身份是指向它在内存中所处的指针(在内存中的位置) a1就是引用这个具体位置的名称 使用type()函数查看其类型 其值就是'abc' 自定义类型使用class 对象的类型用于描述对象的内部表示及其支持的方法和操作 创建特定类型的对象,也将该对象称为该类

  • Python对象转JSON字符串的方法

    本文实例讲述了Python对象转JSON字符串的方法.分享给大家供大家参考,具体如下: import json class JSONObject(object): def __init__(self): self.name = 'Ahan' self.email = 'www@qq.com' self.age = 26 if __name__ == '__main__': o = JSONObject() print json.dumps(o, default=lambda o: o.__dic

  • Python中的对象,方法,类,实例,函数用法分析

    本文实例分析了Python中的对象,方法,类,实例,函数用法.分享给大家供大家参考.具体分析如下: Python是一个完全面向对象的语言.不仅实例是对象,类,函数,方法也都是对象. 复制代码 代码如下: class Foo(object):     static_attr = True     def method(self):         pass foo = Foo() 这段代码实际上创造了两个对象,Foo和foo.而Foo同时又是一个类,foo是这个类的实例. 在C++里类型定义是在编

  • Python 读写文件和file对象的方法(推荐)

    1.open 使用open打开文件后一定要记得调用文件对象的close()方法.比如可以用try/finally语句来确保最后能关闭文件. file_object = open('thefile.txt') try:      all_the_text = file_object.read( ) finally:      file_object.close( ) 注:不能把open语句放在try块里,因为当打开文件出现异常时,文件对象file_object无法执行close()方法. 2.读文

  • Java利用序列化实现对象深度clone的方法

    本文实例讲述了Java利用序列化实现对象深度clone的方法.分享给大家供大家参考.具体实现方法如下: ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(obj); ByteArrayInputStream byteIn = new ByteArrayInputStream(by

  • Python对象中__del__方法起作用的条件详解

    对象的__del__是对象在被gc消除回收的时候起作用的一个方法,它的执行一般也就意味着对象不能够继续引用. 示范代码如下: class Demo: def __del__(self): print("calling __del__") obj = Demo() del obj 程序执行结果如下: grey@DESKTOP-3T80NPQ:/mnt/e/01_workspace/02_programme_language/03_python/03_OOP/2017/08$python

  • python对象与json相互转换的方法

    在网络通信中,json是一种常用的数据格式,对于python来讲,将类转化为json数据以及将json数据转化为对象是一件非常容易的事情. 下面给出两者转化的方法 # -*- coding: UTF-8 -*- import json #自定义类 class MyClass: #初始化 def __init__(self): self.a=2 self.b='bb' ########################## #创建MyClass对象 myClass=MyClass() #添加数据c

随机推荐