诚意
诚意如你,当一诚的态度对待

导航

 

 

1     序列化

1.1   什么是序列化

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

 

序列:列表、元祖、字符串、bytes

序列化:字符串、bytes

1.2   为什么要转成字符串?

能够在网络上传输的只能是bytes,

能够存储在文件里的只有bytes和str

序列化的目的

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

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

3、使程序更具维护性。

 

 

1.3   为什么要有序列化模块?

比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?

现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。

但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。

你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢?

没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串,

但是你要怎么把一个字符串转换成字典呢?

聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。

eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。

BUT!强大的函数有代价。安全性是其最大的缺点

想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。

而使用eval就要担这个风险。

所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构)

s="{1:2}"
d='[1,2,3]'
print(eval(s))      #{1: 2}
print(eval(d))      #[1, 2, 3]

 

# eval 要谨慎的使用,用户的输入/网络上接收的数据/文件中的内容

# eval('import os;os.remove('c:')')

 

 

2     json模块—通用但限制多

Json模块提供了四个功能:dumps、dump、loads、load

# json

# dumps loads

    # 在内存中做数据转换 :

        # dumps 数据类型 转成 字符串 序列化  (在内存中操作)

        # loads 字符串 转成 数据类型 反序列化

# dump load

    # 直接将数据类型写入文件,直接从文件中读出数据类型

        # dump 数据类型 写入 文件 序列化

        # load 文件 读出 数据类型 反序列化

# json是所有语言都通用的一种序列化格式

    # 只支持 列表 字典 字符串 数字

    # 字典的key必须是字符串

 

2.1   dumps和loads

dic = {'key' : 'value','key2' : 'value2'}
ret = json.dumps(dic)   #序列化
print(dic,type(dic))    #{'key': 'value', 'key2': 'value2'} <class 'dict'>
print(ret,type(ret))    #{"key": "value", "key2": "value2"} <class 'str'>

res = json.loads(ret)   #反序列化
print(res,type(res))    #{'key': 'value', 'key2': 'value2'} <class 'dict'>

2.1.1 问题一:

可以看到序列化和反序列化后key值的类型-----》字符串类型,

所以对于字典的约束:key是字符串类型

dic = {1:'value',2:'value2'}
ret = json.dumps(dic)   #序列化
print(dic,type(dic))    #{1: 'value', 2: 'value2'} <class 'dict'>
print(ret,type(ret))    #{"1": "value", "2": "value2"} <class 'str'>
res = json.loads(ret)   #反序列化
print(res,type(res))    #{'1': 'value', '2': 'value2'} <class 'dict'>

 

 

2.1.2 问题二:

 

dic = {1 : [1,2,3],2 : (4,5,'aa')}
ret = json.dumps(dic)  # 序列化
print(dic,type(dic))    #{1: [1, 2, 3], 2: (4, 5, 'aa')} <class 'dict'>
print(ret,type(ret))    #{"1": [1, 2, 3], "2": [4, 5, "aa"]} <class 'str'>
res = json.loads(ret) # 反序列化
print(res,type(res))    #{'1': [1, 2, 3], '2': [4, 5, 'aa']} <class 'dict'>

 

 

2.1.3 问题三:

s = {1,2,'aaa'}
json.dumps(s)       #TypeError

2.1.4 问题四:

json.dumps({(1,2,3):123})   #TypeError: keys must be a string

2.1.5 问题五:不支持连续的存 取

dic = {'key1' : 'value1','key2' : 'value2'}
with open('json_file','a') as f:
    json.dump(dic,f)
    json.dump(dic,f)
    json.dump(dic,f)

with open('json_file','r') as f:
    dic = json.load(f)
print(dic.keys())

2.1.6 常用于文件操作传输

#向文件中记录字典
dic = {'key' : 'value','key2' : 'value2'}
ret = json.dumps(dic)
with open('json_file','a') as f:
    f.write(ret)

#从文件中读取字典
with open('json_file','r') as f:
    str_dic = f.read()
di = json.loads(str_dic)
print(di)

 

注意:

json只能识别一个字典,如果多个字典在一行,当反序列化的时候就会报错,所以可以把字典放不同的行,并在读文件时,readline一行一行读

 

# 需求 :就是想要把一个一个的字典放到文件中,再一个一个取出来???

dic = {'key1' : 'value1','key2' : 'value2'}

with open('json_file','a') as f:
    str_dic = json.dumps(dic)
    f.write(str_dic+'\n')
    str_dic = json.dumps(dic)
    f.write(str_dic + '\n')
    str_dic = json.dumps(dic)
    f.write(str_dic + '\n')

with open('json_file','r') as f:
    for line in f:
        dic = json.loads(line.strip())
        print(dic.keys())

 

2.2   结论:

# json 在所有的语言之间都通用 : json序列化的数据 在python上序列化了 那在java中也可以反序列化

# 能够处理的数据类型是非常有限的 : 字符串 列表 字典 数字

# 字典中的key只能是字符串

 

2.3   dump和load

dic = {'key1' : 'value1','key2' : 'value2'}
with open('json_file','a') as f:
    json.dump(dic,f)

with open('json_file','r') as f:
    dic = json.load(f)
print(dic)

 

结论:Dump和load直接操作文件

 

2.4   其他参数

data = {'username':['李华','二愣子'],'sex':'male','age':16}
json_dic2 = json.dumps(data,sort_keys=True,indent=4,separators=(',',':'),ensure_ascii=False)
print(json_dic2)

结果:

{

    "age":16,

    "sex":"male",

    "username":[

        "李华",

        "二愣子"

    ]

}

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的中文即可正常显示。)

indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json

separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。

 

sort_keys:将数据根据keys的值进行排序。

 


3     pickle模块
 

用于序列化的两个模块

json,用于字符串 和 python数据类型间进行转换

pickle,用于python特有的类型 和 python的数据类型间进行转换

支持在python中几乎所有的数据类型

 

pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load  (不仅可以序列化字典,列表...可以把python中任意的数据类型序列化

 

3.1   特点:

(1)支持在python中几乎所有的数据类型

(2)dumps 序列化的结果只能是字节

(3)只能在python中使用

(4)在和文件操作的时候,需要用rb wb的模式打开文件

(5)可以多次dump 和 多次load

3.2   案例:

3.2.1 案例一:

import pickle
dic = {(1,2,3):{'a','b'},1:'abc'}
ret = pickle.dumps(dic)
print(ret)
#结果:b'\x80\x03}q\x00(K\x01K\........
#结论:dumps 序列化的结果只能是字节
print(pickle.loads(ret))    #{(1, 2, 3): {'b', 'a'}, 1: 'abc'}

3.2.2 案例二:

import pickle
dic = {(1,2,3):{'a','b'},1:'abc'}
with open('pickle_file','wb') as f:
    pickle.dump(dic,f)

with open('pickle_file','rb') as f:
    ret = pickle.load(f)
print(ret,type(ret))        #{(1, 2, 3): {'b', 'a'}, 1: 'abc'} <class 'dict'> 

3.2.3 案例三:可以多次dump 和 多次load

dic = {(1,2,3):{'a','b'},1:'abc'}
dic1 = {(1,2,3):{'a','b'},2:'abc'}
dic2 = {(1,2,3):{'a','b'},3:'abc'}
dic3 = {(1,2,3):{'a','b'},4:'abc'}
with open('pickle_file','wb') as f:
    pickle.dump(dic, f)
    pickle.dump(dic1, f)
    pickle.dump(dic2, f)
    pickle.dump(dic3, f)
with open('pickle_file','rb') as f:
    ret = pickle.load(f)
    print(ret,type(ret))
    ret = pickle.load(f)
    print(ret,type(ret))
    ret = pickle.load(f)
    print(ret, type(ret))
    ret = pickle.load(f)
    print(ret, type(ret))

3.3   异常处理

with open('pickle_file','rb') as f:

    while True:

        try:

            ret = pickle.load(f)

            print(ret,type(ret))

        except EOFError:

            break
posted on 2018-08-21 22:04  诚意  阅读(180)  评论(0)    收藏  举报