序列化模块

什么叫序列化——

将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化

什么叫反序列化-——

将序列化后的内容转换回来的过程就叫做 反序列化

为什么要序列化——

1,以某种存储形式使自定义对象持久化

2,将对象从一个地方传递到另一个地方

3,使程序更具维护性

序列化的最终目的就是为了保存下来(比如以文件形式存在硬盘上),或者是发送出去(比如通过网络发送一个类到服务器上),但是文件是没有字典这个概念的,所以我们只能将字典转化成字符串放到文件中。

为什么反序列化不使用eval()——

eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
BUT!强大的函数有代价。安全性是其最大的缺点。
想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。 而使用eval就要担这个风险。

json模块

所有语言都通用,他能序列化的数据是有限的:

序列化中的内容只能包含:字典 列表 数字 字符串,如果是元祖——自动转成列表的样子

json模块提供了四个功能:dumps,dump,loads,load

#dumps()和loads()

ret = json.dumps({"k1":"k2"})#序列化,将字典变成了字符串
print(repr(ret),type(ret))#'{"k1": "k2"}' <class 'str'>
ret2 = json.dumps((1,2,3))#'[1, 2, 3]' <class 'str'>
print(repr(ret2),type(ret2))

ret2=json.loads(ret)#反序列化,将字符串格式的字典转换为数据结构,字符串只能包含一个数据结构,但是这个数据结构可以嵌套
print(repr(ret2),type(ret2))#{'k1': 'k2'} <class 'dict'>


#dump()和load()

#dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
# load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
f = open("json_1","w")
dic={"k1":"k2"}
json.dump(dic,f) #  这么写进去是没有办法换行的,再使用load()反序列化时,就会报错
json.dump((1,2,3,4,5),f)
f.close()

f = open("json_1")
dic2=json.load(f)#把文件中的内容转换成数据结构返回
f.close()
print(dic2)

#当文件中每一行都是一个数据结构时,可以读取其中的每一行
f=open("json_1","r")
for i in f:
    print(json.loads(i))
f.close()
#
f1=open("json_1","w")
str = json.dumps({"k2":"v2"})
f1.write(str+"\n")#追加时注意换行符的位置,要判断换行符在前还是在后
f1.close()

json的dumps()

json.dumps()会将回将内部字符装换成编码,将ensure_ascii参数设置为False就能变回原字符

>>> import json
>>> json.dumps("魏文刚")
'"\\u9b4f\\u6587\\u521a"'
>>> json.dumps("魏文刚",ensure_ascii=False)
'"魏文刚"'

自定义序列化规则

import datetime
import json

dic = {
    'k1':123,
    'ctime':datetime.datetime.now()
}

class MyEncoder(json.JSONEncoder):
    def default(self, o): # o是数据类型
        if isinstance(o,datetime.datetime):
            return o.strftime('%Y-%m-%d')
        else:
            return super(MyEncoder,self).default(o)

v = json.dumps(dic,cls=MyEncoder)
print(v)
# {"k1": 123, "ctime": "2018-05-15"}

pickle模块

pickle是python特有的,能够序列化任何数据类型(包括对象),python专有的不能和其他语言兼容,结果是bytes

方法和json一样,dumps,loads,dump,load

读写文件时,要用b模式

import pickle
ret = pickle.dumps({"k":"v"})
print(ret)

#b'\x80\x03}q\x00X\x01\x00\x00\x00kq\x01X\x01\x00\x00\x00vq\x02s.'
#用pickle序列化的类型,反序列化也必须用pickle

pickle模块再向文件中写时不用换行,读的时候每次读一个数据类型

import pickle
f = open("a","wb")
dict = {"用户名":178973,"用户名2":21324325}
pickle.dump(dict,f)
pickle.dump([1,2,3,4,5,6],f)
f.close()
f = open("a","rb")
print(pickle.load(f))
print(pickle.load(f))
#{'用户名': 178973, '用户名2': 21324325}
#[1, 2, 3, 4, 5, 6]

shelve模块

只限于python语言,能转换所有的数据类型,只有一种使用方法,使用方法类似于字典

shelve 只提供一个open,shelve.open('文件名')拿到一个文件句柄,这个文件句柄就可以当做字典操作
正常情况下shelve打开的文件句柄感知不到值的修改,设置writeback = True就可以保存修改内容了

flag参数

flag=c  默认参数,打开文件进行读写,必要时创建该文件

flag=w  打开文件进行读写,如果文件不存在,不会创建他

flag=n  打开文件进行读写,但总创建一个新的空白文件

import shelve
f = shelve.open('shelve_file')
f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'}  #直接对文件句柄操作,就可以存入数据
f.close()

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

修改

f=shelve.open("222")
print(f["q"])
f["q"].append("c")
print(f["q"])
f.close()
#
f=shelve.open("222",writeback=True)
print(f["q"])
f["q"].append("a")
print(f["q"])
f.close()
#运行结果
#[1, 2, 3, 4, 5]
#[1, 2, 3, 4, 5]
#[1, 2, 3, 4, 5]
#[1, 2, 3, 4, 5, 'a']

 

posted @ 2017-11-15 18:53  瓜田月夜  阅读(197)  评论(0编辑  收藏  举报