推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

一文了解Python常见的序列化操作

   2023-07-03 网络整理佚名1020
核心提示:内部对象的序列化。序列化一个对象到文件中从文件中反序列化一个对象二进制数据中反序列化一个对象如果要使用与语言无法的序列化那么我们应该使用json。序列化的数据类型有:文件中反序列化一个对象,该方法与(file).反序列化对象。格式文档中反序列化成一个对象一般情况下这样使用似乎也没什么问题,但如果对类型要求很高的场景就需要明确定义转化的方法了。对象,这时就需要使用到json.

0x00

使用依赖于语言但独立于机器的二进制文件来读取和写入对象。 这种二进制格式还和语言版本有关,序列化格式不兼容不同的版本。

一般用于内部对象的序列化。

一般包括:

booleans, integers,floating point numbers,complex numbers
strings, bytes, bytearray, tuple, list, set, frozenset, dictionary
code object
None, Ellipsis, StopIteration

.pyc 的主要作用是支持“编译”.pyc 文件的读写。 这也是版本不兼容的原因。 想要使用序列化/反序列化的开发人员应该使用模块。

常用方法

marshal.dump(value, file[, version])
复制代码

将对象序列化到文件

marshal.dumps(value[, version])
复制代码

序列化一个对象并返回一个字节对象

marshal.load(file)
复制代码

从文件反序列化对象

marshal.loads(bytes)
复制代码

从字节二进制数据反序列化对象

0x01

模块还可以读取和写入二进制形式的对象。 与提供基本的序列化能力相比,序列化的应用更加广泛。

序列化数据也是语言相关的,即Java等其他语言无法读取序列化的二进制数据。 如果我们想使用与该语言不兼容的序列化,那么我们应该使用 json。 下面将进行说明。

可以序列化的数据类型有:

如果对象不支持序列化,则会抛出该异常。

常用方法

pickle.dump(obj, file, protocol=None, *, fix_imports=True)
复制代码

将obj对象序列化为文件file,该方法相当于(file, ).dump(obj)。

pickle.dumps(obj, protocol=None, *, fix_imports=True)
复制代码

将 obj 对象序列化为字节二进制数据。

pickle.load(file, *, fix_imports=True, encoding="ASCII", errors="strict")
复制代码

从文件中反序列化一个对象,该方法相当于(file).load()。

pickle.loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")
复制代码

从二进制数据反序列化对象。

序列化示例

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)
复制代码

执行完之后,又多了一份数据。 文件夹中的文件

serialization
├── data.pickle
├── pickles.py
└── unpickles.py
复制代码

反序列化示例

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 是一种独立于语言的、非常通用的数据交互格式。 因为它具有与 和 类似的 API。

常用方法

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 文件

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 对象

json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
复制代码

从文件反序列化为对象

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与的转换对照表

列表、nt、float、int- 和 float-

对于基本类型、序列以及包含基本类型的集合类型json来说,序列化都可以做得很好。

序列化示例

>>> 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"]'
复制代码

反序列化示例

>>> 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']
复制代码

由于情况比较复杂

例如定义多个对象的 json 文档

.json

{
 "__complex__": true,
 "real": 42,
 "imaginary": 36
}
复制代码

要将这个json文档反序列化为对象,需要定义转换方法

# 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)
# 执行结果
# 
# (42+36j)
复制代码

如果不指定,json文档默认会转为dict

# 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)
# 执行结果
# 
# {'__complex__': True, 'real': 42, 'imaginary': 36}
复制代码

可以看到json文档已经转换成了dict对象。

一般情况下,这样使用似乎没有什么问题,但如果场景要求类型较高,就需要明确定义转换方法。

除了参数之外,还可以使用json。

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)
# 执行结果
# 
# [2.0, 1.0]
复制代码

因为json模块不会自动完成所有类型的序列化,所以对于不支持的类型会直接抛出。

>>> 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 "", line 1, in 
 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
复制代码

对于不支持序列化的类型,比如自定义类型,需要使用 来定义转换逻辑。

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文档中的日期格式转换为.date对象,那么我们就需要使用json。

# 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"}
# 
# {'birthday': datetime.date(2019, 6, 14), 'name': 'jack'}
复制代码

最后,小编个人有六年的开发经验。 我做了资料的整合,有完整的编程学习路线、学习资料和工具。 想要这些素材的可以关注小编,后台私信:发送“01”即可领取,希望对您有帮助。

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON