Python之序列化模块json、pickle和shelve

有时候需要将某种类型的数据转化为字符串类型,那么这个过程叫做序列化,反之则叫做反序列化。在看《Python核心编程》中介绍了几个序列化模块,有pickle、marshal、shelve及DBM风格的模块。不过还是json、pickle和shelve最为常用吧!

python-json-data

0x00 关于序列化

序列化就是将一些类似字典、列表等内容转化为一个字符串的过程,序列就是字符串的意思。其主要用在数据存储上及网络上传输的时候。而从字符串转为数据类型的过程叫做反序列化。

serialization序列化的目的主要有以下3个方面:

  1. 以某种存储形式使自定义对象持久化
  2. 将对象从一个地方传递到另一个地方
  3. 使程序更具维护性

0x01 json模块及使用方法

json为通用的序列化格式,其最大的优点就是通用性,而缺点就是只有很少的一部分数据类型可以通过json转化为字符串。在python中其可以转化数字、字符串、列表、字典和元祖。

json主要提供了4个方法:

  • dumps
  • loads
  • dump
  • load

其中dumps和loads主要是对数据在内存中进行序列化。

import json

dic = {'a':1,'b':2}
ret = json.dumps(dic)
print(ret,type(ret))  #{"a": 1, "b": 2} <class 'str'>

di = json.loads(ret)
print(di,type(di))  #{'a': 1, 'b': 2} <class 'dict'>

而dump与load的是将对象进行序列化后通过文件句柄写入文件中。

import json

dic = {'a':1,'b':2}
f = open('f',mode='w')
json.dump(dic,f)
f.close()

f = open('f',mode='r')
ret = json.load(f)
print(ret)
f.close()

而在写入文件过程中,则为一次性写入无法一行一行的写入。对于需要一行一行写入的对象则可以通过dumps将对象在内存中转为为字符串在一行一行的写入,之后在一行一行的loads即可(效率感人( >﹏<。)~呜呜呜…… ),具体实现见下代码。

import json

l = [{1:1,2:2},{3:3,4:4}]
f = open('f',mode='w')
for i in l:
    res = json.dumps(i)
    f.write(res+'\n')
f.close()
'''
{"1": 1, "2": 2}
{"3": 3, "4": 4}
'''

f = open('f',mode='r')
l1 = []
for i in f:
    res = json.loads(i.strip())
    l1.append(res)
print(l1)   #[{'1': 1, '2': 2}, {'3': 3, '4': 4}]

对于含有中文的数据类型,在使用dump的时候写入文件里会产生“乱码”,不过可以通过设置ensure_ascii=False来让“乱码”消失。

import json

dic = {'a':'你好'}
f = open('f',mode='w')
json.dump(dic,f)    #文件中内容{"a": "\u4f60\u597d"}
f.close()

f = open('f',mode='w',encoding='utf-8')
json.dump(dic,f,ensure_ascii=False)    #{"a": "你好"}
f.close()

对于dump还有一些别的参数,待用到时再去查阅吧!

0x02 pickle模块及使用方法

pickle相较于json就更加强大了,什么数据类型都可以进行序列号,不过呢由于不是通用类型,所以其只能序列号python中的数据类型,一些自定义对象也可以进行序列化,不过都必须要是python能理解的内容,而且部分反序列号依赖python代码。

pickle的使用方法与json几乎一样,都是用过dumps、loads和dump、load对数据进行序列化,不过由于其是将序列化后以bytes类型进行存储,因而在使用dump、load的时候需要使用wb和rb的方式对文件进行写入与读取。

import pickle
import time

struct_time  = time.localtime(1000000000)
f = open('f1',mode='wb')
pickle.dump(struct_time,f)
f.close()

f = open('f1',mode='rb')
ret = pickle.load(f)
f.close()
print(ret)  #time.struct_time(tm_year=2001, tm_mon=9, tm_mday=9, tm_hour=9, tm_min=46, tm_sec=40, tm_wday=6, tm_yday=252, tm_isdst=0)

学会了json,其实pickle也就会了,非常的简单。

0x03 shelve模块及使用方法

shelve是python3才有的序列化模块,其最大的优点就是操作十分简单,通过open方法将文件打开后,其序列化的东西存储类似一个字典的形式。

import shelve

dic = {1:1,2:2}
f = shelve.open('shelve')
f['dic'] = dic
f.close()

f = shelve.open('shelve')
e = f['dic']
print(e)

在存储后其会生成3个文件,分别是.bak .dat .dir,看不懂,不过可以忽略。每一个序列化的对象对存储在一个类似值的位置出,可以通过键来调用。

虽然shelve使用非常的简单,不过其也有一些缺点,比如在默认情况下其是不会记录持久化对象的修改,需要设置writeback=True才行。

import shelve

dic = {1:1,2:2}
f = shelve.open('shelve')
f['dic'] = dic
f.close()

f = shelve.open('shelve')
f['dic']['a'] = 'dddd'
e = f['dic']
f.close()
print(e)    #{1: 1, 2: 2}

f = shelve.open('shelve',writeback=True)
f['dic']['a'] = 'dddd'
e = f['dic']
f.close()
print(e)    #{1: 1, 2: 2, 'a': 'dddd'}

发表评论