序列化

在程序运行的过程中,所有的变量都储存在内存中,例如定义一个dict

d=dict(name='Bob',age=20,score=88)

可以随时修改变量,比如把name修改为'Bill',但是一旦程序结束,变量所占用的内存就被OS完全回收。如果没有把修改后的'Bill'存储到磁盘上,下次重新运行程序,变量又会被初始化为'Bob'。

序列化

把变量从内存中变为可存储或传输的过程称为序列化,在Python中称为pickling,其他语言中称为serilization、marshalling、flattening等等。

序列化后,可以把序列化后的内容写入磁盘,或者通过网络传输到其他机器上。

反序列化:把变量内容从序列化的对象重新读到内存中,unpickling。

Python的序列化在pickle模块中,举例,我们想把之前创建的Dict对象序列化并写入文件中:

import pickle
d=dict(name='Bob',age=20,score=88)
pickle.dumps(d)
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00Bobq\x02X\x03\x00\x00\x00ageq\x03K\x14X\x05\x00\x00\x00scoreq\x04KXu.'

pickle.dumps()方法把任意对象序列化为一个bytes,然后就可以把这个bytes写入文件。

或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object:

f=open('dump.txt','wb')
pickle.dump(d,f)
f.close()

我们直接查看dump.txt文件时,看到的是一堆混乱的内容,但这些都是Python保存的对象内部信息。

之后我们再进行反序列化,把对象从磁盘读到内存,可以先把内容读到一个bytes,然后用pickle.loads()方法反序列化出对象,也可以直接用pickle.load()方法直接从一个file-like Object中直接反序列化出对象。

#pickle.load() 参数是file-like Object
with open('dump.txt','rb') as f:
d2=pickle.load(f) d2
{'name': 'Bob', 'age': 20, 'score': 88} #pickle.loads() 参数是二进制Data
with open('dump.txt','rb') as f:
d=f.read()
N=pickle.loads(d) N
{'name': 'Bob', 'age': 20, 'score': 88}

Python的序列化库pickle可以保存数据的类型,例如将一个dict进行序列化后,再进行反序列化,得到的仍是一个dict(这一点很重要),且其值与之前的dict相同。

存在的问题:python的Pickle只能作用于Python,不能用于其他语言,甚至Python不同的版本也不兼容。因此,只能用pickle保存那些不重要的内容,这样不能成功的反序列化也没关系。

JSON

上文结尾提到,pickle不能用于python之外的语言序列化对象,为了解决这一问题,可以把对象序列化为标准格式,比如XML;但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,而且比XML快,并且可以直接在Web页面中读取,非常方便。

JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型的对应情况如下:

JSON Python
{} dict
[] list
'String' str
123.456 int或float
true/false True/Flase
null None

Python → Json

Python内置的json模块提供了完善的Python对象到JSON格式的转换。举例,如何把Python对象转化为JSON:

import json
d=dict(name='Bob',age=20,score=90)
json.dumps(d) '{"name": "Bob", "age": 20, "score": 90}'

json.dumps()返回一个str,其中的内容就是标准JSON。同理,json.dump()方法可以直接把JSON写入一个file-like Object。

with open('Json.txt','w') as f:
json.dump(d,f) with open('Json.txt','r') as f:
print(f.read())
{"name": "Bob", "age": 20, "score": 90}

Json → Python

要把JSON反序列化为Python对象,则要用loads()或者load()方法,前者把JSON的字符串反序列化,后者直接从file-like Object中读取字符串并且反序列化

#json.loads() 从JSON字符串中反序列化
S=json.dumps(d)
json.loads(S)
{'name': 'Bob', 'age': 20, 'score': 90} #json.load() 从file-like Object中反序列化
with open('Json.txt','r') as f:
S2=json.load(f) S2
{'name': 'Bob', 'age': 20, 'score': 90}

由于JSON标准规定JSON编码是UTF-8,所以我们总是可以正确地在Python的str与JSON字符串间转换。

JSON复杂对象的序列化

从之前的表格中,可以看出几种常用类型从JSON到Python间格式的变化。

但是并不存在一种class间的变化,即无法将我们自定义的class类化为JSON,如果直接用dumps转化一个class时,会出现TypeError的错误

import json
class Student():
def __init__(self,name,age,score):
self.name=name
self.age=age
self.score=score S=Student('Bob',20,90)
print(json.dumps(S)) TypeError: Object of type Student is not JSON serializable

这是因为,默认情况下,dumps不知道如何将Student实例变为一个JSON的{}对象

解决方法:

通过修改dumps()的参数default,我们需要为要进行转化的对象专门写一个转换函数,再把函数作为default参数传进去:

def Student2dict(S):
return {
'name':S.name,
'age':S.age,
'score':S.score
}
S=Student('Bob',20,90)
print(json.dumps(S,default=Student2dict))

但是该转换函数,只对Student对象起作用,对于其他的类对象,同样不起作用。

一个通用、简便的任意class到JSON转换的语句为:

print(json.dumps(S,default=lambda obj:obj.__dict__))

因为class通常都有一个__dict__属性,它是一个dict,用来存储实例变量。当然也有例外,比如定义了__slot__的class(__slot__属性:规定了类只能有的属性)。

JSON逆序列化

与dumps类似,需要手写一个从JSON到class的方法,并将其作为json.loads()方法的object_hook参数传入。

def Dict2Student(D):
return Student(D['name'],D['age'],D['score'])
S2=json.loads(D,object_hook=Dict2Student)
print(S2)
<__main__.Student object at 0x00000165B0EF8CC8>

打印出的是反序列化的Student实例对象。

总结:

1、几个方法的用法:

d=json.dumps(S) #json序列化
json.dump(f,S) #json序列化 将S序列化保存到file-like Object f中
S=json.loads(d) #json逆序列化
S=json.load(f) #从file-like Object f中逆序列化数据到S中

关于load方法,不是json.load(f,S) 而是 S=json.load(f)

2、修改json.dumps方法的default参数,一种简单、通用的class对象序列化为dict的方法:

D=json.dumps(S,default=lambda obj:obj.__dict__)

3、逆序列化时,要修改的loads方法的参数为object_hook

4、如果想要正常显示中文,需要在dump时添加参数ensure_ascii=False

Python:序列化 pickle JSON的更多相关文章

  1. Python 序列化 pickle/cPickle模块

    Python 序列化 pickle/cPickle模块 2013-10-17 Posted by yeho Python序列化的概念很简单.内存里面有一个数据结构,你希望将它保存下来,重用,或者发送给 ...

  2. Python序列化之json与pickle

    1.json介绍 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于JavaScript Progra ...

  3. python序列化模块json和pickle

    序列化相关 1. json 应用场景: json模块主要用于处理json格式的数据,可以将json格式的数据转化为python的字典,便于python处理,同时也可以将python的字典或列表等对象转 ...

  4. python 序列化之JSON和pickle详解

    JSON模块 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使用了类 ...

  5. Python序列化-pickle和json模块

    Python的“file-like object“就是一种鸭子类型.对真正的文件对象,它有一个read()方法,返回其内容.但是,许多对象,只要有read()方法,都被视为“file-like obj ...

  6. python序列化模块 json&&pickle&&shelve

    #序列化模块 #what #什么叫序列化--将原本的字典.列表等内容转换成一个字符串的过程叫做序列化. #why #序列化的目的 ##1.以某种存储形式使自定义对象持久化 ##2.将对象从一个地方传递 ...

  7. Python序列化,json&pickle&shelve模块

    1. 序列化说明 序列化可将非字符串的数据类型的数据进行存档,如字典.列表甚至是函数等等 反序列化,将通过序列化保存的文件内容反序列化即可得到数据原本的样子,可直接使用 2. Python中常用的序列 ...

  8. python使用pickle,json等序列化dict

    import pickle, json, csv, os, shutil class PersistentDict(dict): ''' Persistent dictionary with an A ...

  9. Python序列化之Json基础

    python的序列化就是将python的基本对象转换为字符串的过程,反之则是反序列化. 序列化类型: -> import json import pickle 序列化定义: 序列化:对象.列表. ...

随机推荐

  1. 获取nginx日志状态码百分比脚本

    #!/bin/bash pwd=/app/nginx/logs/access.log for num1 in `cat $pwd | awk '{print $9}' | grep -Ei " ...

  2. Linux下升级py2.6到2.7

    python2.6版本有很多局限性:最重要的就是,当前最新的pip版本已经不再支持python2.6:这给我们安装很多python库增加了很多不便:所以这里把我升级python2.6--2.7的过程及 ...

  3. AWS SAA_C01 考试分享。

    Saa-c01 经验分享! 序言1.介绍自己的情况,我是一个做后台开发的初级java程序员.还是处于在写业务逻辑的阶段,我对aws可谓是啥都不懂,纯种的小白,完全是从0基础开始学习的.希望分享一些我的 ...

  4. 蓝桥杯试题 基础练习 2n皇后问题以及n皇后问题

    在学习2n皇后之前,我们应该认识一下n皇后问题: 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上.你的任务是,对于 ...

  5. ApacheCN JavaWeb 译文集 20211017 更新

    使用 Spring5 构建 REST Web 服务 零.前言 一.一些基本知识 二.在 Spring5 中使用 Maven 构建 RESTfulWeb 服务 三.Spring 中的 Flux 和 Mo ...

  6. 最近公共祖先-LCA

    题目描述 时间限制:1.2s 内存限制:256.0MB 问题描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入格式 第一行包含三个正整数\(N\),\(M\),\(S\),分别 ...

  7. Redis为什么是单线程,高并发快的3大原因详解

    出处知乎:https://zhuanlan.zhihu.com/p/58038188 Redis的高并发和快速原因 1.redis是基于内存的,内存的读写速度非常快: 2.redis是单线程的,省去了 ...

  8. 【VUE】vue中遍历数组和对象

    一.遍历对象 对象数据 cities:{ "A":[{ "id": 56, "spell": "aba", " ...

  9. linux 批量替换文件内容及查找某目录下所有包含某字符串的文件

    转载请注明来源:https://www.cnblogs.com/hookjc/ 1. sed C代码   grep -rl matchstring somedir/ | xargs sed -i 's ...

  10. 前端-Data URI Scheme

    了解Data URI scheme,首要要掌握一些URI.URL的基本知识,很多做移动端上开发的同学对这两个基本概念掌握的不够,本文首先会对这两个基本概念做一些简单的介绍. 基本概念 <HTTP ...