- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章一篇文章了解Python中常见的序列化操作由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
0x00 marshal 。
marshal使用的是与python语言相关但与机器无关的二进制来读写python对象的。这种二进制的格式也跟python语言的版本相关,marshal序列化的格式对不同的版本的python是不兼容的.
marshal一般用于python内部对象的序列化.
一般地包括:
marshal的主要作用是对python“编译”的.pyc文件读写的支持。这也是marshal对python版本不兼容的原因。开发者如果要使用序列化/反序列化,那么应该使用pickle模块.
常见的方法 。
1
|
marshal.dump(value,
file
[, version])
|
序列化一个对象到文件中 。
1
|
marshal.dumps(value[, version])
|
序列化一个对象并返回一个bytes对象 。
1
|
marshal.load(
file
)
|
从文件中反序列化一个对象 。
1
|
marshal.loads(bytes)
|
从bytes二进制数据中反序列化一个对象 。
0x01 pickle 。
pickle模块也能够以二进制的方式对python对象进行读写。相比marshal提供基本的序列化能力,pickle的序列化应用更加广泛.
pickle序列化后的数据也是与python语言相关的,即其它语言例如java无法读取由python通过pickle序列化的二进制数据。如果要使用与语言无法的序列化那么我们应该使用json。下文将会说明.
能被pickle序列化的数据类型有:
如果pickle一个不支持序列化的对象时将会抛出picklingerror.
常见的方法 。
1
|
pickle.dump(obj,
file
, protocol
=
none,
*
, fix_imports
=
true)
|
将obj对象序列化到一个file文件中,该方法与pickler(file, protocol).dump(obj)等价.
1
|
pickle.dumps(obj, protocol
=
none,
*
, fix_imports
=
true)
|
将obj对象序列化成bytes二进制数据.
1
|
pickle.load(
file
,
*
, fix_imports
=
true, encoding
=
"ascii"
, errors
=
"strict"
)
|
从file文件中反序列化一个对象,该方法与unpickler(file).load()等价.
1
|
pickle.loads(bytes_object,
*
, fix_imports
=
true, encoding
=
"ascii"
, errors
=
"strict"
)
|
从二进制数据bytes_object反序列化对象.
序列化例子 。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import
pickle
# 定义了一个包含了可以被序列化对象的字典
data
=
{
'a'
: [
1
,
2.0
,
3
,
4
+
6j
],
'b'
: (
"character string"
, b
"byte string"
),
'c'
: {none, true, false}
}
with
open
(
'data.pickle'
,
'wb'
) as f:
# 序列化对象到一个data.pickle文件中
# 指定了序列化格式的版本pickle.highest_protocol
pickle.dump(data, f, pickle.highest_protocol)
|
执行之后在文件夹中多一个data.pickle文件 。
serialization ├── data.pickle ├── pickles.py └── unpickles.py 。
反序列化例子 。
1
2
3
4
5
6
7
8
9
10
11
12
|
import
pickle
with
open
(
'data.pickle'
,
'rb'
) as f:
# 从data.pickle文件中反序列化对象
# pickle能够自动检测序列化文件的版本
# 所以这里可以不用版本号
data
=
pickle.load(f)
print
(data)
# 执行后结果
# {'a': [1, 2.0, 3, (4+6j)], 'b': ('character string', b'byte string'), 'c': {false, true, none}}
|
0x02 json json是与语言无关,非常通用的数据交互格式。在python它与marshal和pickle一样拥有相似的api.
常见的方法 。
1
|
json.dump(obj, fp,
*
, skipkeys
=
false, ensure_ascii
=
true, check_circular
=
true, allow_nan
=
true,
cls
=
none, indent
=
none, separators
=
none, default
=
none, sort_keys
=
false,
*
*
kw)
|
序列化对象到fp文件中 。
1
|
json.dumps(obj,
*
, skipkeys
=
false, ensure_ascii
=
true, check_circular
=
true, allow_nan
=
true,
cls
=
none, indent
=
none, separators
=
none, default
=
none, sort_keys
=
false,
*
*
kw)
|
将obj序列化成json对象 。
1
|
json.load(fp,
*
,
cls
=
none, object_hook
=
none, parse_float
=
none, parse_int
=
none, parse_constant
=
none, object_pairs_hook
=
none,
*
*
kw)
|
从文件中反序列化成一个对象 。
1
|
json.loads(s,
*
, encoding
=
none,
cls
=
none, object_hook
=
none, parse_float
=
none, parse_int
=
none, parse_constant
=
none, object_pairs_hook
=
none,
*
*
kw)
|
从json格式文档中反序列化成一个对象 。
json与python对象的转化对照表 。
json | python |
---|---|
object | dict |
list,tuple | array |
str | string |
int, float, int- & float-derived enums | number |
true | true |
false | false |
none | null |
对于基本类型、序列、以及包含基本类型的集合类型json都可以很好的完成序列化工作.
序列化例子 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
>>>
import
json
>>> json.dumps([
'foo'
, {
'bar'
: (
'baz'
, none,
1.0
,
2
)}])
'["foo", {"bar": ["baz", null, 1.0, 2]}]'
>>>
print
(json.dumps(
"\"foo\bar"
))
"\"foo\bar"
>>>
print
(json.dumps(
'\u1234'
))
"\u1234"
>>>
print
(json.dumps(
'\\'
))
"\\"
>>>
print
(json.dumps({
"c"
:
0
,
"b"
:
0
,
"a"
:
0
}, sort_keys
=
true))
{
"a"
:
0
,
"b"
:
0
,
"c"
:
0
}
>>>
from
io
import
stringio
>>> io
=
stringio()
>>> json.dump([
'streaming api'
], io)
>>> io.getvalue()
'["streaming api"]'
|
反序列化例子 。
1
2
3
4
5
6
7
8
9
|
>>>
import
json
>>> json.loads(
'["foo", {"bar":["baz", null, 1.0, 2]}]'
)
[
'foo'
, {
'bar'
: [
'baz'
, none,
1.0
,
2
]}]
>>> json.loads(
'"\\"foo\\bar"'
)
'"foo\x08ar'
>>>
from
io
import
stringio
>>> io
=
stringio(
'["streaming api"]'
)
>>> json.load(io)
[
'streaming api'
]
|
对于object的情况就复杂一些了 。
例如定义了复数complex对象的json文档 。
complex_data.json 。
1
2
3
4
5
|
{
"__complex__"
: true,
"real"
:
42
,
"imaginary"
:
36
}
|
要把这个json文档反序列化成python对象,就需要定义转化的方法 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# coding=utf-8
import
json
# 定义转化函数,将json中的内容转化成complex对象
def
decode_complex(dct):
if
"__complex__"
in
dct:
return
complex
(dct[
"real"
], dct[
"imaginary"
])
else
:
return
dct
if
__name__
=
=
'__main__'
:
with
open
(
"complex_data.json"
) as complex_data:
# object_hook指定转化的函数
z
=
json.load(complex_data, object_hook
=
decode_complex)
print
(
type
(z))
print
(z)
# 执行结果
# <class 'complex'>
# (42+36j)
|
如果不指定object_hook,那么默认将json文档中的object转成dict 。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# coding=utf-8
import
json
if
__name__
=
=
'__main__'
:
with
open
(
"complex_data.json"
) as complex_data:
# 这里不指定object_hook
z2
=
json.loads(complex_data.read())
print
(
type
(z2))
print
(z2)
# 执行结果
# <class 'dict'>
# {'__complex__': true, 'real': 42, 'imaginary': 36}
|
可以看到json文档中的object转成了dict对象.
一般情况下这样使用似乎也没什么问题,但如果对类型要求很高的场景就需要明确定义转化的方法了.
除了object_hook参数还可以使用json.jsonencoder 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import
json
class
complexencoder(json.jsonencoder):
def
default(
self
, obj):
if
isinstance
(obj,
complex
):
# 如果complex对象这里转成数组的形式
return
[obj.real, obj.imag]
# 默认处理
return
json.jsonencoder.default(
self
, obj)
if
__name__
=
=
'__main__'
:
c
=
json.dumps(
2
+
1j
,
cls
=
complexencoder)
print
(
type
(c))
print
(c)
# 执行结果
# <class 'str'>
# [2.0, 1.0]
|
因为json模块并不是对所有类型都能够自动完成序列化的,对于不支持的类型,会直接抛出typeerror.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
>>>
import
datetime
>>> d
=
datetime.datetime.now()
>>> dct
=
{
'birthday'
:d,
'uid'
:
124
,
'name'
:
'jack'
}
>>> dct
{
'birthday'
: datetime.datetime(
2019
,
6
,
14
,
11
,
16
,
17
,
434361
),
'uid'
:
124
,
'name'
:
'jack'
}
>>> json.dumps(dct)
traceback (most recent call last):
file
"<pyshell#19>"
, line
1
,
in
<module>
json.dumps(dct)
file
"/library/frameworks/python.framework/versions/3.7/lib/python3.7/json/__init__.py"
, line
231
,
in
dumps
return
_default_encoder.encode(obj)
file
"/library/frameworks/python.framework/versions/3.7/lib/python3.7/json/encoder.py"
, line
199
,
in
encode
chunks
=
self
.iterencode(o, _one_shot
=
true)
file
"/library/frameworks/python.framework/versions/3.7/lib/python3.7/json/encoder.py"
, line
257
,
in
iterencode
return
_iterencode(o,
0
)
file
"/library/frameworks/python.framework/versions/3.7/lib/python3.7/json/encoder.py"
, line
179
,
in
default
raise
typeerror(f
'object of type {o.__class__.__name__} '
typeerror:
object
of
type
datetime
is
not
json serializable
|
对于不支持序列化的类型例如datetime以及自定义类型,就需要使用jsonencoder来定义转化的逻辑.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import
json
import
datetime
# 定义日期类型的jsonencoder
class
datetimeencoder(json.jsonencoder):
def
default(
self
, obj):
if
isinstance
(obj, datetime.datetime):
return
obj.strftime(
'%y-%m-%d %h:%m:%s'
)
elif
isinstance
(obj, datetime.date):
return
obj.strftime(
'%y-%m-%d'
)
else
:
return
json.jsonencoder.default(
self
, obj)
if
__name__
=
=
'__main__'
:
d
=
datetime.date.today()
dct
=
{
"birthday"
: d,
"name"
:
"jack"
}
data
=
json.dumps(dct,
cls
=
datetimeencoder)
print
(data)
# 执行结果
# {"birthday": "2019-06-14", "name": "jack"}
|
现在我们希望发序列化时,能够将json文档中的日期格式转化成datetime.date对象,这时就需要使用到json.jsondecoder了.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
# coding=utf-8
import
json
import
datetime
# 定义decoder解析json
class
datetimedecoder(json.jsondecoder):
# 构造方法
def
__init__(
self
):
super
().__init__(object_hook
=
self
.dict2obj)
def
dict2obj(
self
, d):
if
isinstance
(d,
dict
):
for
k
in
d:
if
isinstance
(d[k],
str
):
# 对日期格式进行解析,生成一个date对象
dat
=
d[k].split(
"-"
)
if
len
(dat)
=
=
3
:
date
=
datetime.date(
int
(dat[
0
]),
int
(dat[
1
]),
int
(dat[
2
]))
d[k]
=
date
return
d
if
__name__
=
=
'__main__'
:
d
=
datetime.date.today()
dct
=
{
"birthday"
: d,
"name"
:
"jack"
}
data
=
json.dumps(dct,
cls
=
datetimeencoder)
# print(data)
obj
=
json.loads(data,
cls
=
datetimedecoder)
print
(
type
(obj))
print
(obj)
# 执行结果
# {"birthday": "2019-06-14", "name": "jack"}
# <class 'dict'>
# {'birthday': datetime.date(2019, 6, 14), 'name': 'jack'}
|
0x03 总结一下 。
python常见的序列化工具有marshal、pickle和json。marshal主要用于python的.pyc文件,并与python版本相关。它不能序列化用户定义的类.
pickle是python对象的序列化工具则比marshal更通用些,它可以兼容python的不同版本。json是一种语言无关的数据结构,广泛用于各种网络应用尤其在rest api的服务中的数据交互.
0x04 学习资料 。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我的支持.
原文链接:https://juejin.im/post/5d0362755188255e780b6815 。
最后此篇关于一篇文章了解Python中常见的序列化操作的文章就讲到这里了,如果你想了解更多关于一篇文章了解Python中常见的序列化操作的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我开始在 Ethereum blockchain 上了解如何开发智能合约以及如何写 web-script用于与智能合约交互(购买、销售、统计......)我得出了该怎么做的结论。我想知道我是否正确理解
我正在 UIView 中使用 CATransform3DMakeRotation,并且我正在尝试进行 45º,变换就像向后放置一样: 这是我拥有的“代码”,但显然没有这样做。 CATransform3
我目前正在测试 WebRTC 的功能,但我有一些脑逻辑问题。 WebRTC 究竟是什么? 我只读了“STUN”、“P2P”和其他...但是在技术方面什么是正确的 WebRTC(见下一个) 我需要什么
我在看 DelayedInit在 Scala in Depth ... 注释是我对代码的理解。 下面的 trait 接受一个非严格计算的参数(由于 => ),并返回 Unit .它的行为类似于构造函数
谁能给我指出一个用图片和简单的代码片段解释 WCF 的资源。我厌倦了谷歌搜索并在所有搜索结果中找到相同的“ABC”文章。 最佳答案 WCF 是一项非常复杂的技术,在我看来,它的文档记录非常少。启动和运
我期待以下 GetArgs.hs打印出传递给它的参数。 import System.Environment main = do args main 3 4 3 :39:1: Coul
private int vbo; private int ibo; vbo = glGenBuffers(); ibo = glGenBuffers(); glBindBuffer(GL_ARRAY_
我正在尝试一个 for 循环。我添加了一个 if 语句以在循环达到 30 时停止循环。 我见过i <= 10将运行 11 次,因为循环在达到 10 次时仍会运行。 如果有设置 i 的 if 语句,为什
我正在尝试了解 WSGI 的功能并需要一些帮助。 到目前为止,我知道它是一种服务器和应用程序之间的中间件,用于将不同的应用程序框架(位于服务器端)与应用程序连接,前提是相关框架具有 WSGI 适配器。
我是 Javascript 的新手,我正在尝试绕过 while 循环。我了解它们的目的,我想我了解它们的工作原理,但我在使用它们时遇到了麻烦。 我希望 while 值自身重复,直到两个随机数相互匹配。
我刚刚偶然发现Fabric并且文档并没有真正说明它是如何工作的。 我有根据的猜测是您需要在客户端和服务器端都安装它。 Python 代码存储在客户端,并在命令运行时通过 Fabric 的有线协议(pr
我想了解 ConditionalWeakTable .和有什么区别 class ClassA { static readonly ConditionalWeakTable OtherClass
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 5年前关闭。 Improve this questi
我还没有成功找到任何可以引导我理解 UIPickerView 和 UIPickerView 模型的好例子。有什么建议吗? 最佳答案 为什么不使用默认的 Apple 文档示例?这是来自苹果文档的名为 U
我在看foldM为了获得关于如何使用它的直觉。 foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a 在这个简单的例子中,我只返回 [Just
答案What are _mm_prefetch() locality hints?详细说明提示的含义。 我的问题是:我想要哪一个? 我正在处理一个被重复调用数十亿次的函数,其中包含一些 int 参数。
我一直在读这个article了解 gcroot 模板。我明白 gcroot provides handles into the garbage collected heap 然后 the handle
提供了一个用例: 流处理架构;事件进入 Kafka,然后由带有 MongoDB 接收器的作业进行处理。 数据库名称:myWebsite集合:用户 并且作业接收 users 集合中的 user 记录。
你好 我想更详细地了解 NFS 文件系统。我偶然发现了《NFS 图解》这本书,不幸的是它只能作为谷歌图书提供,所以有些页面丢失了。有人可能有另一个很好的资源,这将是在较低级别上了解 NFS 的良好开始
我无法理解这个问题,哪个更随机? rand() 或: rand() * rand() 我发现这是一个真正的脑筋急转弯,你能帮我吗? 编辑: 凭直觉,我知道数学答案是它们同样随机,但我忍不住认为,如果您
我是一名优秀的程序员,十分优秀!