什么是序列化?

将一组或多组数据结构转化成一个字符串的过程就叫做序列化

它的目的:

序列化的结构是字符串,准确的说是bytes类型,方便存储

方便于网络传输,

既然序列化是从数据类型到字符串的过程,那是不是可以在反序列化的时候使用eval呢

事实证明:eval对于很多类型反序列化的时候改变了原来数据的类型,再一个就是不安全

序列化: 数据结构  --》 字符串

反序列化:字符串  --》数据结构

一 json

json 是大部分语言都支持的的序列化格式,但是对于python而言支持的数据类型有限。

它支持的类型有:字典,列表,数字类型,而且json里面只允许使用双引号,

还有一点,当将两个以上的数据类型(即使是同一个类型)写入一行,读取也会报错

json的序列化

下面看看json的一个例子

import json
dic={'a':1}
x=None
res=json.dumps(dic)
print(res,type(res)) #{"a": 1} <class 'str'> 这里面的是双引号
print(json.dumps(x)) #由None转化成了null

如果写入文件呢

import json
dic={'a':1,'name':'xinxin'}
with open('user.json','w',encoding='utf-8') as f:
f.write(json.dumps(dic))
#查看文件的结果为:{"a": 1, "name": "xinxin"} 着里面都变成双引号了

那上面的写入文件是不是可以简便点呢?答案是可以

json.dump(dic,open('user_new.json','w',encoding='utf-8'))
#结果是一样的

json的反序列化

# json.dump(dic,open('user_new.json','w',encoding='utf-8'))
# with open('user.json','r',encoding='utf-8') as f:
# user=json.loads(f.read())
# print(user['name']) #上面的太麻烦,简便点
user=json.load(open('user.json','r',encoding='utf-8'))
print(user['name'])

json对字符串的处理

# json_str='{"count":1}'
# print(json.loads(json_str)['count']) #答案为 1 说明是可以解析出来 json_str="{'count':1}"
print(json.loads(json_str)['count']) #json对于这种格式会报错 #如果在文件里面写单引号会怎么样?
#答案:json使用load和loads都会报错

json的一行内是不能存储两个类型的数据类型的,即使是同一个类型的两个,那么怎么解决呢

a={'':'a'}
b={'':'b'}
c={'':'c'} msg=''
msg+=json.dumps(a)+'\n'
msg+=json.dumps(b)+'\n'
msg+=json.dumps(c)+'\n'
# with open('user_new.json','w',encoding='utf-8') as f:
# f.write(msg) # res=json.load(open('user_new.json','r',encoding='utf-8'))
# print(res) #报错 json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 11)
with open('user_new.json','r',encoding='utf-8') as f:
for i in f:
print(json.loads(i.strip())) '''
{'1': 'a'}
{'2': 'b'}
{'3': 'c'}
原本字典里面的整数变成了字符串,这是一个缺陷
'''

上面的例子是使用dumps拼接然后使用loads读取的例子,那么使用load是否可以读取呢

res=json.load(open('user_new.json','r',encoding='utf-8'))
print(res) #报错 json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 11)
#之后我将着三行数据只留下一行,发现可以读取了
#看来,存入多行内容到文件时,
# 1 分别使用dumps转化成字符串 +上\n
# 2 反序列化的时候,按行读取去掉\n,再使用loads反序列化

如果对于拼接后的字符串使用dump直接写入呢

json.dump(msg,open('user.json','w',encoding='utf-8')) #文件中的结果 "{\"1\": \"a\"}\n{\"2\": \"b\"}\n{\"3\": \"c\"}\n"
#结果就变得不一样了

下面是一个json序列化和反序列化中文的情况

dicc={'序号':'one'}
# res=json.dumps(dicc)
# ret=json.loads(res)
# print(ret) #正常显示中文
# f=open('user.json','w',encoding='utf-8')
# json.dump(dicc,f) #查看文件 {"\u5e8f\u53f7": "one"}
# f.close() # f=open('user.json','r',encoding='utf-8')
# res=json.load(f)
# print(res) #正常显示中文
# f.close() f=open('user.json','w',encoding='utf-8')
json.dump(dicc,f,ensure_ascii=False) #查看文件{"序号": "one"} 正常显示中文了
f.close() #json使用dumps序列化后,使用loads是能正常显示中文的,这个是变量的情况,在内存中
#但是写入文件里面,查看文件的内容却是二进制,当然还是可以dump导出看出中文
#要想在文件里面也显示为中文,使用 ensure_ascii=False
总结:

dumps序列化 loads反序列化 只在内存中操作数据 主要用于网络传输 和多个数据与文件打交道
dump序列化 load反序列化 主要用于一个数据直接存在文件里—— 直接和文件打交道

json的其他参数说明

Serialize obj to a JSON formatted str.(字符串表示的json对象)
Skipkeys:默认值是False,如果dict的keys内的数据不是python的基本类型(str,unicode,int,long,float,bool,None),设置为False时,就会报TypeError的错误。此时设置成True,则会跳过这类key
ensure_ascii:,当它为True的时候,所有非ASCII码字符显示为\uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入json的中文即可正常显示。)
If check_circular is false, then the circular reference check for container types will be skipped and a circular reference will result in an OverflowError (or worse).
If allow_nan is false, then it will be a ValueError to serialize out of range float values (nan, inf, -inf) in strict compliance of the JSON specification, instead of using the JavaScript equivalents (NaN, Infinity, -Infinity).
indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json
separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。
default(obj) is a function that should return a serializable version of obj or raise TypeError. The default simply raises TypeError.
sort_keys:将数据根据keys的值进行排序。
To use a custom JSONEncoder subclass (e.g. one that overrides the .default() method to serialize additional types), specify it with the cls kwarg; otherwise JSONEncoder is used.

举例:json的格式话输出:

data={'username':['李华','二愣子'],'sex':'male','age':16}
json_dic=json.dumps(data,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False)
print(json_dic)
'''
显示结果为:
{
"age":16,
"sex":"male",
"username":[
"李华",
"二愣子"
]
}
如果indent=0 就顶格写了
'''

二 pickle

pickle支持python中几乎所有的数据类型,包括自定义的类和对象

它和json的区别:json序列化之后是字符串,pickle是bytes类型

dic={'k1':'v1','k2':'v2','k3':'v3'}
str_dic=pickle.dumps(dic) #序列化
print(str_dic) #显示的一串bytes类型的字符串 dic2=pickle.loads(str_dic) #反序列化
print(dic2) #{'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} import time
# struct_time=time.localtime(1000000000)
# print(struct_time)
# f=open('pickle_file','wb')
# pickle.dump(struct_time,f) #它写入文件查看时时乱码
# f.close()
#读取文件
# f=open('pickle_file','rb')
# struct_time2=pickle.load(f)
# print(struct_time2.tm_year) #成功显示2001
# f.close() #将文件的写入和读取使用其他编码时报错,因此,pickle只能使用bytes类型的方式操作

其他:

这时候机智的你又要说了,既然pickle如此强大,为什么还要学json呢?
这里我们要说明一下,json是一种所有的语言都可以识别的数据结构。
如果我们将一个字典或者序列化成了一个json存在文件里,那么java代码或者js代码也可以拿来用。
但是如果我们用pickle进行序列化,其他语言就不能读懂这是什么了~
所以,如果你序列化的内容是列表或者字典,我们非常推荐你使用json模块
但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用python对这个数据进行反序列化的话,那么就可以使用pickle

三 shelve

shelve也是python中提供序列化的模块,使用方法简单

shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似。

缺点:

适合读,不适合更新,在writeback时会把所有的数据都重新写入,结果就是可能消耗内存很多,写入耗时;
不能并发的读写,不过可以使用Unix文件锁进行控制(fcntl);

import shelve
f=shelve.open('shelve_file')
f['key']={'int':10, 'float':9.5, 'string':'Sample data'}
f.close()

上面的例子执行后,会产生3个文件,类似于mysql的myisam表

shelve_file.bak   查看:'key', (0, 72)

shelve_file.dat    查看:乱码

shelve_file.dir     查看: 'key', (0, 72)

下面时读取文件

 import shelve
f1=shelve.open('shelve_file')
existing=f1['key'] ##取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing) #可以读出内容{'int': 10, 'float': 9.5, 'string': 'Sample data'}

这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB

import shelve
f = shelve.open('shelve_file', flag='r')
existing = f['key']
f.close()
print(existing)

由于shelve在默认情况下是不会记录待持久化对象的任何修改的,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。

import shelve
f1 = shelve.open('shelve_file')
print(f1['key'])
f1['key']['new_value'] = 'this was not here before'
f1.close() f2 = shelve.open('shelve_file', writeback=True)
print(f2['key'])
f2['key']['new_value'] = 'this was not here before'
f2.close()

writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。

序列化模块json--pickle--shelve的更多相关文章

  1. python 全栈开发,Day25(复习,序列化模块json,pickle,shelve,hashlib模块)

    一.复习 反射 必须会 必须能看懂 必须知道在哪儿用 hasattr getattr setattr delattr内置方法 必须能看懂 能用尽量用__len__ len(obj)的结果依赖于obj. ...

  2. python开发模块基础:序列化模块json,pickle,shelve

    一,为什么要序列化 # 将原本的字典.列表等内容转换成一个字符串的过程就叫做序列化'''比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?现在我们能想到的方法就是存在文 ...

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

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

  4. python 常用模块 time random os模块 sys模块 json & pickle shelve模块 xml模块 configparser hashlib subprocess logging re正则

    python 常用模块 time random os模块 sys模块 json & pickle shelve模块 xml模块 configparser hashlib  subprocess ...

  5. python序列化: json & pickle & shelve 模块

    一.json & pickle & shelve 模块 json,用于字符串 和 python数据类型间进行转换pickle,用于python特有的类型 和 python的数据类型间进 ...

  6. python全栈开发day17-常用模块collections,random,time,os,sys,序列化(json pickle shelve)

    1.昨日内容回顾 1.正则表达式     # 正则表达式 —— str           # 检测字符串是否符合要求     # 从大段的文字中找到符合要求的内容 1).元字符 #. # 匹配除换行 ...

  7. day6_python序列化之 json & pickle & shelve 模块

    一.json & pickle & shelve 模块 json,用于字符串 和 python数据类型间进行转换pickle,用于python特有的类型 和 python的数据类型间进 ...

  8. Day 21 序列化模块_Json,Pickle,Shelve

    序列化 , 数据类型,列表 元组, 字符串 只有字符串能被写入文件中. 能在网络上传输的只能是bytes - 字符串 把要传输的和要存储的内容转换成字符串. 字符串 转换回 要传输和存储的内容 序列化 ...

  9. Python全栈之路----常用模块----序列化(json&pickle&shelve)模块详解

    把内存数据转成字符,叫序列化:把字符转成内存数据类型,叫反序列化. Json模块 Json模块提供了四个功能:序列化:dumps.dump:反序列化:loads.load. import json d ...

  10. Python模块:shutil、序列化(json&pickle&shelve)、xml

    shutil模块: 高级的 文件.文件夹.压缩包 处理模块 shutil.copyfileobj(fscr,fdst [, length])   # 将文件内容拷贝到另一个文件中 import shu ...

随机推荐

  1. Microsoft - Find Biggest Node

    public Node findBiggest (Node n1, Node n2){ Node c1 = n1; Node c2 = n2; boolean isPositive = false; ...

  2. signal()信号操作

    一.函数描述 #include <signal.h> typedef void (*sighandler_t)(int);sighandler_t signal(int signum, s ...

  3. 注册表禁用和启用USB端口

    USB端口禁用把下面代码另存为文件:USB_Disable.batcSCript \\AppServices\netlogon\USB_Disable.vbs--------------------- ...

  4. 实现多线程的方式之实现Callable接口

    package com.hls.juc; import java.util.concurrent.Callable;import java.util.concurrent.ExecutionExcep ...

  5. FastAdmin 插件的 Git 开发流程(简明)

    FastAdmin 插件的 Git 开发流程(简明) cms zip 安装 包安装 删除 addons 里的 cms 使用 mklink 软链接到 cms 插件 Git 仓库 修改 cms 插件 gi ...

  6. enjoy dollar vs cash dollar

    當 enJoy 卡 客 戶 憑 enJoy 卡 於 enJoy 卡 「 特 約 商 戶 」 簽 賬 消 費 , 累 積 之 enJoy Dollars 及 Cash Dollars 可 在 同 一 交 ...

  7. asm数据文件迁移(asm–>asm)

    rman迁移操作 [oracle@localhost oradata]$ rman target /   Recovery Manager: Release 10.2.0.3.0 - Producti ...

  8. JVM 之:Class 类文件结构

    类文件结构 Class 文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在 Class 文件中,中间没有添加任何分隔符,这使得整个 Class 文件中存储的内容几乎全部都是 ...

  9. hadoop最新版本介绍之dkhadoop版本选择

    Hadoop对于从事互联网工作的朋友来说已经非常熟悉了,相信在我们身边有很多人正在转行从事hadoop开发的工作,理所当然也会有很多hadoop入门新手.Hadoop开发太过底层,技术难度远比我们想象 ...

  10. 1、zookeeper集群安装

    前提准备3台centos7.0虚拟机 c7003:192.168.70.103 c7004:192.168.70.104 c7005:192.168.70.105 并在三台虚拟机上配置hosts为 1 ...