- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python序列化与反序列化相关知识总结由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
在程序运行的过程中,所有的变量都是在内存中,比如,定义一个 dict:
1
|
d
=
dict
(name
=
'bob'
, age
=
20
, score
=
88
)
|
可以随时修改变量,比如把 name 改成 ‘bill',但是一旦程序结束,变量所占用的内存就被操作系统全部回收。如果没有把修改后的 ‘bill' 存储到磁盘上,下次重新运行程序,变量又被初始化为 ‘bob'.
我们把变量从内存中变成可存储或传输的过程称之为序列化,在 python 中叫 pickling,在其他语言中也被称之为 serialization,marshalling,flattening 等等,都是一个意思。 序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上.
。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即 unpickling.
python 提供了 pickle 模块来实现序列化。首先,我们尝试把一个对象序列化并写入文件:
1
2
3
4
5
6
|
in
[
1
]:
import
pickle
in
[
2
]: d
=
dict
(name
=
'bob'
, age
=
20
, score
=
88
)
in
[
3
]: pickle.dumps(d)
out[
3
]: b
'\x80\x04\x95$\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x03bob\x94\x8c\x03age\x94k\x14\x8c\x05score\x94kxu.'
|
pickle.dumps() 方法把任意对象序列化成一个 bytes,然后,就可以把这个 bytes 写入文件。或者用另一个方法 pickle.dump() 直接把对象序列化后写入一个 file-like object:
1
2
3
4
5
6
7
|
in
[
5
]: f
=
open
(
'dump.txt'
,
'wb'
)
in
[
6
]: d
=
dict
(name
=
'bob'
, age
=
20
, score
=
88
)
in
[
7
]: pickle.dump(d, f)
in
[
8
]: f.close()
|
看看写入的 dump.txt 文件,一堆乱七八糟的内容,这些都是 python 保存的对象内部信息.
当我们要把对象从磁盘读到内存时,可以先把内容读到一个 bytes,然后用 pickle.loads() 方法反序列化出对象,也可以直接用 pickle.load() 方法从一个 file-like object 中直接反序列化出对象。我们打开另一个 python 命令行来反序列化刚才保存的对象:
1
2
3
4
5
6
7
8
|
in
[
23
]: f
=
open
(
'dump.txt'
,
'rb'
)
in
[
24
]: d
=
pickle.load(f)
in
[
25
]: f.close()
in
[
26
]: d
out[
26
]: {
'name'
:
'bob'
,
'age'
:
20
,
'score'
:
88
}
|
变量的内容又回来了! 。
当然,这个变量和原来的变量是完全不相干的对象,它们只是内容相同而已.
pickle 的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于 python,并且可能不同版本的 python 彼此都不兼容,因此,只能用 pickle 保存那些不重要的数据,不能成功地反序列化也没关系.
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如 xml,但更好的方法是序列化为 json,因为 json 表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。json 不仅是标准格式,并且比 xml 更快,而且可以直接在 web 页面中读取,非常方便。 。
json 表示的对象就是标准的 javascript 语言的对象,json 和 python 内置的数据类型对应如下:
json类型 | python类型 |
---|---|
{} | dict |
[] | list |
“string” | str |
1234.56 | int 或 float |
true/false | true/false |
null | none |
python 内置的 json 模块提供了非常完善的 python 对象到 json 格式的转换。我们先看看如何把 python对象变成一个 json:
1
2
3
4
5
6
7
8
9
|
in
[
27
]:
import
json
in
[
28
]: d
=
dict
(name
=
'bob'
, age
=
20
, score
=
88
)
in
[
29
]: json.dumps(d)
out[
29
]:
'{"name": "bob", "age": 20, "score": 88}'
in
[
30
]:
type
(json.dumps(d))
out[
30
]:
str
|
dumps() 方法返回一个 str,内容就是标准的 json。类似的,dump() 方法可以直接把 json 写入一个 file-like object.
要把 json 反序列化为 python 对象,用 loads() 或者对应的 load() 方法,前者把 json 的字符串反序列化,后者从 file-like object 中读取字符串并反序列化:
1
2
3
4
5
6
7
|
in
[
31
]: json_str
=
'{"age": 20, "score": 88, "name": "bob"}'
in
[
32
]: json.loads(json_str)
out[
32
]: {
'age'
:
20
,
'score'
:
88
,
'name'
:
'bob'
}
in
[
33
]:
type
(json.loads(json_str))
out[
33
]:
dict
|
由于 json 标准规定 json 编码是 utf-8,所以我们总是能正确地在 python 的 str 与 json 的字符串之间转换.
python 的 dict 对象可以直接序列化为 json 的 {},不过,很多时候,我们更喜欢用 class . 表示对象,比如定义 student 类,然后序列化:
1
2
3
4
5
6
7
8
9
10
|
import
json
class
student(
object
):
def
__init__(
self
, name, age, score):
self
.name
=
name
self
.age
=
age
self
.score
=
score
s
=
student(
'bob'
,
20
,
88
)
print
(json.dumps(s))
|
运行代码,毫不留情地得到一个 typeerror:
1
2
3
|
traceback (most recent call last):
...
typeerror:
object
of
type
student
is
not
json serializable
|
错误的原因是 student 对象不是一个可序列化为 json 的对象.
如果连 class 的实例对象都无法序列化为 json,这肯定不合理! 。
别急,我们仔细看看 dumps() 方法的参数列表,可以发现,除了第一个必须的 obj 参数外,dumps() 方法还提供了一大堆的可选参数:
这些可选参数就是让我们来定制 json 序列化。前面的代码之所以无法把 student 类实例序列化为 json,是因为默认情况下,dumps() 方法不知道如何将 student 实例变为一个 json 的 {} 对象.
可选参数 default 就是把任意一个对象变成一个可序列为 json 的对象,我们只需要为 student 专门写一个转换函数,再把函数传进去即可:
1
2
3
4
5
6
7
8
|
in
[
40
]: s.name
out[
40
]:
'bob'
in
[
41
]: s.age
out[
41
]:
20
in
[
42
]: s.score
out[
42
]:
88
|
1
2
3
4
5
6
|
def
student2dict(std):
return
{
'name'
: std.name,
'age'
: std.age,
'score'
: std.score
}
|
这样,student 实例首先被 student2dict() 函数转换成 dict,然后再被顺利序列化为 json:
1
|
print
(json.dumps(s, default
=
student2dict))
|
不过,下次如果遇到一个 teacher 类的实例,照样无法序列化为 json。再写一个函数 也可以,但是我们可以偷个懒,把任意 class 的实例变为 dict:
1
|
print
(json.dumps(s, default
=
lambda
obj: obj.__dict__))
|
因为通常 class 的实例都有一个 __dict__ 属性,它就是一个 dict,用来存储实例变量。也有少数例外,比如定义了 __slots__ 的 class.
同样的道理,如果我们要把 json 反序列化为一个 student 对象实例,loads() 方法首先转换出一个 dict 对象,然后,我们传入的 object_hook 函数负责把 dict 转换为 student 实例:
1
2
|
def
dict2student(d):
return
student(d[
'name'
], d[
'age'
], d[
'score'
])
|
运行结果如下:
1
2
3
4
5
6
7
8
|
in
[
48
]: json_str
=
'{"age": 20, "score": 88, "name": "bob"}'
in
[
49
]:
def
dict2student(d):
...:
return
student(d[
'name'
], d[
'age'
], d[
'score'
])
...:
in
[
50
]:
print
(json.loads(json_str, object_hook
=
dict2student))
<__main__.student
object
at
0x1065c6f70
>
|
打印出的是反序列化的 student 实例对象.
对中文进行 json 序列化时,json.dumps() 提供了一个 ensure_ascii 参数,观察该参数对结果的影响:
1
2
3
4
5
|
import
json
obj
=
dict
(name
=
'小明'
, age
=
20
)
s
=
json.dumps(obj, ensure_ascii
=
true)
print
(s)
|
python 语言特定的序列化模块是pickle,但如果要把序列化搞得更通用、更符合 web 标准,就可以使用 json 模块.
json 模块的 dumps() 和 loads() 函数是定义得非常好的接口的典范。当我们使用时,只需要传入一个必须的参数。但是,当默认的序列化或反序列机制不满足我们的要求时,我们又可以传入更多的参数来定制序列化或反序列化的规则,既做到了接口简单易用,又做到了充分的扩展性和灵活性.
到此这篇关于python序列化与反序列化相关知识总结的文章就介绍到这了,更多相关python序列化与反序列内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/qq_33254766/article/details/117628406 。
最后此篇关于Python序列化与反序列化相关知识总结的文章就讲到这里了,如果你想了解更多关于Python序列化与反序列化相关知识总结的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是 python 的新手。我试图找到我的文本的频率分布。这是代码, import nltk nltk.download() import os os.getcwd() text_file=open(
我对安卓 fragment 感到困惑。我知道内存 fragment 但无法理解什么是 android fragment 问题。虽然我发现很多定义,比如 Android fragmentation re
尝试对 WordPress 进行 dockerise 我发现了这个场景: 2个数据卷容器,一个用于数据库(bbdd),另一个用于wordpress文件(wordpress): sudo docker
这个问题已经有答案了: From the server is there a way to know that my page is being loaded in an Iframe (1 个回答)
我正在玩小型服务器,试图对运行在其上的服务进行docker化。为简化起见,假设我必须主要处理:Wordpress和另一项服务。 在Docker集线器上有许多用于Wordpress的图像,但是它们似乎都
我想要发生的是,当帐户成功创建后,提交的表单应该消失,并且应该出现一条消息(取决于注册的状态)。 如果成功,他们应该会看到一个简单的“谢谢。请检查您的电子邮件。” 如果不是,那么他们应该会看到一条适当
就是这样,我需要为客户添加一个唯一标识符。通过 strip 元数据。这就是我现在完全构建它的方式,但是我只有最后一部分告诉我用户购买了哪个包。 我试着看这里: Plans to stripe 代码在这
我有一个类将执行一些复杂的操作,涉及像这样的一些计算: public class ComplexAction { public void someAction(String parameter
这个问题已经有答案了: maven add a local classes directory to module's classpath (1 个回答) 已关闭10 年前。 我有一些不应更改的旧 E
我使用 fragment 已经有一段时间了,但我经常遇到一个让我烦恼的问题。 fragment 有时会相互吸引。现在,我设法为此隔离了一个用例,它是这样的: Add fragment A(也使用 ad
我的 html 中有一个 ol 列表,上面有行条纹。看起来行条纹是从数字后面开始的。有没有办法让行条纹从数字开始? 我已经包含了正在发生的事情的片段 h4:nth-child(even) {
如何仅使用 css 将附加图像 html 化? 如果用纯 css 做不到,那我怎么能至少用一个图像来做 最佳答案 这不是真正的问题,而是您希望我们为您编写代码。我建议您搜索“css breadcrum
以下是 Joshua 的 Effective Java 的摘录: If you do synchronize your class internally, you can use various te
在这里工作时,我们有一个框向业务合作伙伴提供 XML 提要。对我们的提要的请求是通过指定查询字符串参数和值来定制的。其中一些参数是必需的,但很多不是。 例如,我们要求所有请求都指定一个 GUID 来标
我有 3 个缓冲区,其中包含在 32 位处理器上运行的 R、G、B 位数据。 我需要按以下方式组合三个字节: R[0] = 0b r1r2r3r4r5r6r7r8 G[0] = 0b g1g2g3g4
我最近发现了关于如何使用 History.js、jQuery 和 ScrollTo 通过 HTML5 History API 对网站进行 Ajax 化的要点:https://github.com/br
我们有一个 Spring Boot 应用程序,由于集成需要,它变得越来越复杂——比如在你这样做之后发送一封电子邮件,或者在你之后广播一条 jms 消息等等。在寻找一些更高级别的抽象时,我遇到了 apa
我正在尝试首次实施Google Pay。我面临如何指定gateway和gatewayMarchantId的挑战。 我所拥有的是google console帐户,不知道在哪里可以找到此信息。 priva
昨天下午 3 点左右,我为两个想要从一个 Azure 帐户转移到另一个帐户的网站设置了 awverify 记录。到当天结束时,Azure 仍然不允许我添加域,所以我赌了一把,将域和 www 子域重新指
我正在使用terms facet在elasticsearch服务器中获取顶级terms。现在,我的标签"indian-government"不被视为一个标签。将其视为"indian" "governm
我是一名优秀的程序员,十分优秀!