Python dumps和loads区别详解
简介
在Python中,我们通常需要将数据序列化为JSON格式或其他格式的字符串以便于存储或传输,同时我们还需要将序列化后的字符串反序列化为原始数据类型,这两个过程可以用Python标准库中的json.dumps()
和json.loads()
函数来完成,但是在某些情况下,我们需要使用Python自带的pickle
模块提供的dumps()
和loads()
函数进行序列化和反序列化,本文将会详细讲解这两个函数的使用方法和区别。
dumps()
函数
Python内置的pickle
模块提供了dumps()
函数,可以将Python对象序列化为一个二进制字符串。dumps()
函数的基本用法如下:
import pickle
data = {'name': 'Tom', 'age': 25, 'gender': 'male'}
serialized_data = pickle.dumps(data)
print(serialized_data)
上述代码会将data
字典序列化为一个二进制字符串并打印到控制台上。dumps()
函数还可以接受一个protocol
参数,用来指定序列化的协议版本,具体如下:
protocol=0
(默认):以文本形式打印(ASCII码),不能保存二进制数据,不兼容旧版本python;protocol=1
:以比特串形式打印,能保存二进制数据,不兼容旧版本python;protocol=2
:以比特串形式打印,能保存二进制数据,兼容所有python版本,是Python 2.x版本中pickle使用的版本;protocol=3
:可以压缩数据,但是只有3.0及其以上才支持该协议。
import pickle
data = {'name': 'Tom', 'age': 25, 'gender': 'male'}
# 使用协议1序列化
serialized_data = pickle.dumps(data, protocol=1)
print(serialized_data)
loads()
函数
loads()
函数可以将序列化后的二进制字符串解析为一个Python对象,其基本用法如下:
import pickle
serialized_data = b'\x80\x04\x95\x1a\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x03Tom\x94\x8c\x03age\x94K\x19\x8c\x06gender\x94\x8c\x04male\x94s.'
data = pickle.loads(serialized_data)
print(data)
输出结果为:
{'name': 'Tom', 'age': 25, 'gender': 'male'}
区别与联系
与json.dumps()
和json.loads()
函数相比,pickle.dumps()
和pickle.loads()
函数的主要区别在于,JSON是一种文本格式,适合于存储或传输文本数据,而pickle
是一种二进制格式,适合于存储或传输Python对象。此外,使用pickle
中的序列化和反序列化函数序列化的对象必须在Python环境下才能被反序列化,而使用json
中的函数序列化的对象则可以在任何支持json
格式的环境下反序列化。
另外,json
中的序列化和反序列化函数会更快且更安全,因为pickle
中的函数可以执行任何有效的Python代码,这也容易导致安全问题。
下面我们举两个示例来说明区别:
示例1:序列化一个NumPy数组
import pickle
import json
import numpy as np
# 序列化一个NumPy数组
arr = np.array([1, 2, 3, 4, 5])
arr_pickle = pickle.dumps(arr)
arr_json = json.dumps(arr.tolist())
# 反序列化
arr_pickle_unserialized = pickle.loads(arr_pickle)
arr_json_unserialized = np.array(json.loads(arr_json))
# 验证
print(arr_pickle_unserialized == arr)
print(arr_json_unserialized == arr)
输出结果为:
True
True
从输出结果可以看出,pickle
和json
序列化和反序列化NumPy
数组的结果是一样的。
示例2:序列化和反序列化自定义函数
import pickle
def add(x, y):
return x + y
add_pickle = pickle.dumps(add)
add_unpickle = pickle.loads(add_pickle)
print(add, add_pickle, add_unpickle)
输出结果为:
<function add at 0x7fcf767931f0> b'\x80\x04\x95\x0e\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\x03add\x94\x93\x94.' <function add at 0x7fcf767a93a0>
从以上输出结果可以看出,在使用pickle
序列化和反序列化自定义函数时,反序列化的形式为函数的内存地址而非函数本身,这是因为pickle
只序列化函数的定义而不会保存其状态。所以如果需要在另外一个Python环境中使用这个函数,必须重新定义这个函数。
总结
pickle
和json
都是Python中常用的序列化工具,二者都有其优缺点,根据实际情况选择使用。在使用pickle
时,要注意安全性和可移植性问题。在序列化时指定协议版本时要考虑版本兼容性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python dumps和loads区别详解 - Python技术站