Python之序列化与反序列化(pickle模块与json模块)

在程序运行的过程中,所有的变量都是在内存中,比如定义一个dict1 = {“name”:“zhangsan”,“age”:20},我们对name属性进行修改,改"wangwu",但是一旦程序结束,变量所占用的内存就会被操作系统全部回收,如果没有把修改后的name存储到磁盘上,下次重新运行程序,属性name又会被初始化为"zhangsan"。

这时候就会使用到序列化与反序列化,将序列化后的内容写入磁盘,这里会讲到pickle模块与json模块去实现序列化与反序列化。

序列化与反序列化

在Python中,我们将变量从内存中变成可存储或者是可传输的这个过程我们称之为序列化,即pickling

反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling

例如:将字典存到demo.txt文件中,再从demo.txt文件中将字典重新读取出来

首先实现将字典存到文件中,代码如下:

def writeFile(dict1):
    with open("demo.txt", "w", encoding="utf-8") as f:
        f.write(str(dict1))

将字典从文件重新读取出来,代码如下:

def readFile():
    with open("demo.txt", "r", encoding="utf-8") as f:
        return eval(f.read())

再调用writeFile函数和readFile函数就可以实现字典从文件读取与存入:

if __name__ == '__main__':
    dict1 = {"name": "韩梅梅", "age": 19}
    writeFile(dict1)
    dict2 = readFile()
    print(dict2)
pickle模块

pickle模块可以将任意的对象序列化成二进制的字符串写入到文件中。还可以从文件中读取并且转为写入时候类型。

现有如下这样一个Card类,我们想要将由Card对象组成的列表存到文件中,并且从文件中将其读取出来,该怎样去实现呢?

class Card:
    def __init__(self,cardnum,password,money,lock=False):
        self.cardnum = cardnum
        self.password = password
        self.money = money
        self.lock = lock

这里我们可以用pickle模块去实现对象的序列化以及反序列化,下面将会讲到pickle模块中会用到的几个函数

要使用到pickle模块,我们就要先导入pickle模块

import pickle
1. pickle.dumps(obj)和pickle.dump(obj,file)

pickle.dumps(obj)函数的功能是将obj对象进行序列化

def writeFile(path,cardlist):
    with open(path,"wb") as f:
        f.write(pickle.dumps(cardlist))

pickle.dump(obj,file)函数的功能是将obj对象序列化并且存入到打开的文件中

def writeFile(path,cardlist):
    with open(path,"wb") as f:
        pickle.dump(cardlist,f)
2. pickle.loads(bytes)和pickle.load(file)

pickle.loads(bytes)函数的功能是将二进制的字符串转为对象

def readFile(path):
    with open(path,"rb") as f:
        return pickle.loads(f.read())

pickle.load(file)函数的功能是将文件中的内容读取并且转为对象

def readFile(path):
    with open(path,"rb") as f:
        return pickle.load(f)

在上面我们已经完成了列表的文件存取函数,现在只要调用writeFile函数和readFile函数就可以了

if __name__ == '__main__':
    card1 = Card("101111", "111", 100)
    card2 = Card("101112", "222", 1000)
    card3 = Card("101113", "333", 10000)
    cardlist = [card1, card2, card3]
    path = "pickledemo.txt"
    writeFile(path,cardlist)
    cardlist1 = readFile(path)
    for card in cardlist1:
        print("cardnum: %s\npassword: %s\nmoney: %d"%(card.cardnum,card.password,card.money))
json模块

json模块提供的方法,可以直接将python基本数据类型序列化为json字符串。也可以将json字符串转为python的基本数据类型。

还是以上面的例子为例,现在要将有Card对象组成的字典存到文件中,并且从文件中将其读取出来

要使用到json模块,也要先导入json模块

import json
1. json.dumps(obj,default)
obj:被序列化的对象
default:将对象转为字典的函数

功能:将对象序列化为json字符串

首先我们需要一个可以将Card对象转化为字典的函数,将其传递到default参数中

def obj2dict(card):
    return {"cardnum":card.cardnum,"password":card.password,"money":card.money,"lock":card.lock}

将字典存到文件中

def writeFile(path,carddict):
    with open(path,"w",encoding="utf-8") as fp:
        for card in carddict.values():
            jstr = json.dumps(card, default=obj2dict)
            fp.write(jstr+'\n')
2. json.dump(obj,file,default)
obj:被序列化的对象
file:打开的文件对象
default:将对象转为字典的函数

功能:将对象序列化为json字符串并且写入到打开的文件对象中

def writeFile(path,carddict):
    with open(path,"w",encoding="utf-8") as fp:
        json.dump(carddict, fp, default=obj2dict)
3. json.loads(jsonstr,object_hook)
jsonstr:json字符串
object_hook:将字典转为对象的函数

功能:将字符串反序列化成对象

这里需要一个可以将字典转化为Card对象的函数,将其传递到object_hook参数中

def dict2obj(dict1):
    return Card(dict1["cardnum"],dict1["password"],dict1["money"],dict1["lock"])

从文件中读取数据

def readFile(path):
    with open(path, "r", encoding="utf-8") as fp:
        carddict = {}
        for jstr in fp.readlines():
            card = json.loads(jstr, object_hook=dict2obj)
            carddict[card.cardnum] = card
    return carddict
4. json.load(fp,object_hook)
fp:打开的文件对象
object_hook:将字典转为对象的函数

功能:将打开的文件对象的内容读取并且反序列化成对象

def readFile(path):
    with open(path, "r", encoding="utf-8") as fp:
        carddict = json.load(fp)
    return carddict

最后只要调用writeFile函数和readFile函数就可以实现对象字典的文件存取

猜你喜欢

转载自blog.csdn.net/TaoismHuang/article/details/93229901