在程序运行的过程中,所有的变量都是在内存中,比如定义一个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函数就可以实现对象字典的文件存取