Python常用标准库(pickle序列化和JSON序列化)

常用的标准库

import pickle

使不能直接存储的数据变得可存储,这一过程称为序列化。从文件中取出数据并回复为原始数据类型,这一过程称为反序列化。

[En]

Making data that cannot be stored directly becomes storable, a process called serialization. Take the data out of the file and reply to the original data type, a process called deserialization.

文件中存储的数据只能是字符串或字节流,不能是任何其他数据类型,但如果您想要存储它,则需要对其进行序列化。

[En]

The data stored in the file can only be a string or a byte stream, not any other data type, but you need to serialize it if you want to store it.

Python中的序列化模块叫做 pickle,PHP等其它的一些语言将其称作 serialize 或者 unserialize,每个语言的序列化功能可以序列化它本身的一切数据类型。

现在有一条数据,我现在不需要,但也许当我要用它的时候,最好的办法就是保存它。

[En]

There is a piece of data now, and I don’t need it now, but maybe when I’m going to use it, the best way is to save it.

一般来说,保存这条数据的方式有几种(入库或保存文件),但这条数据非常复杂,保存在数据库中需要特定的数据格式,所以进入数据库非常麻烦。而且我不想破坏数据的原始格式,所以我可以选择将其保存为文件。

[En]

Generally speaking, there are several ways to save this piece of data (into the library or save the file), but this piece of data is very complex, and saving in the database requires a specific data format, so it is very troublesome to enter the database. And I don’t want to destroy the original format of the data, so I can choose to save it as a file.

具体表现为:保存文件时会遇到各种麻烦。

[En]

It is shown as follows: saving the file will encounter all kinds of troubles.

这是我想要保存的一条数据。<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>This is a piece of data that I want to save.</font>*</details>
lst = ['A', 'B', 'C']

直接使用open函数不能将非字符串和非字节流的数据写入文件
with open('data.txt', 'w', encoding='UTF-8') as fp :
    fp.write(lst)
!!! TypeError

将数据转换为字符串会破坏原始数据结构(如果复杂的数据结构几乎没有恢复的可能性)<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>Turning the data into a string destroys the original data structure (if the complex data structure has little possibility of recovery)</font>*</details>
lst = str(lst)

将数据转换为字节流:只能将字符串转换为字节流数据!<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>Turn data into byte streams: you can only turn strings into byte stream data!</font>*</details>

现在可以使用序列化函数将数据序列化为字节流格式,然后将其存储在文件中,在需要时从文件中读取数据,然后像以前一样反序列化数据。并确保原始数据的数据结构不变。

[En]

You can now use the serialization function to serialize the data into a byte stream format, then store it in the file, read it from the file when needed, and then deserialize the data as it used to be. and ensure that the data structure of the original data remains unchanged.

并且您可以序列化该语言中的任何数据类型,即不仅可以序列化基本数据类型,还可以序列化函数、类和对象。

[En]

And you can serialize any data type in the language, that is, not only basic data types, but also functions, classes, and objects.

dumps将任意对象序列化成bytes数据, loads将序列化成为bytes的数据反序列成数据原本的格式。

注意:只能反序列化被序列化的数据

import pickle

这是我想要保存的一条数据。<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>This is a piece of data that I want to save.</font>*</details>
lst = ['A', 'B', 'C']

dumps 把任意对象序列化成bytes
res = pickle.dumps(lst)
print(res)  # b'\x80\x03]q\x00(X\x01\x00\x00\x00Aq\x01X\x01\x00\x00\x00Bq\x02X\x01\x00\x00\x00Cq\x03e.'
print(type(res))  #
序列化后的bytes数据可以写入文件中。

loads 把任意bytes反序列化成为原来的数据
lst = pickle.loads(res)
print(lst)  # ['A', 'B', 'C']
print(type(lst))  #

尝试反序列化其它的bytes数据
char = '你好'
by_char = char.encode()
new_char = pickle.loads(by_char)  # _pickle.UnpicklingError: invalid load key, '\xe4'.

含义和上述的相同,只是这个可以直接操作IO对象,省时省力。

import pickle

这是我想要保存的一条数据。<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>This is a piece of data that I want to save.</font>*</details>
lst = ['A', 'B', 'C']

dumps 和 loads 配合文件操作
序列化后写入文件
with open('test.txt', 'wb') as fp:
    data = pickle.dumps(lst)
    fp.write(data)
读取文件反序列化
with open('test.txt', 'rb') as fp:
    data = fp.read()
    lst = pickle.loads(data)

dump 和 load 配合文件操作
序列化写入文件
with open('test.txt', 'wb') as fp:
    pickle.dump(lst, fp)
读取文件反序列化
with open('test.txt', 'rb') as fp:
    lst = pickle.load(fp)

import json

如果序列化的数据可以以多种语言流通,情况会怎样?每种语言都有自己的语言特点,有些语言的数据是唯一的,那么序列化的数据应该如何流动呢?

[En]

What if the serialized data can be circulated in multiple languages? Each language has its own language characteristics, and the data in some languages is unique, so how should the serialized data flow?

json一般存储为json文件。

python中支持JSON序列化的数据一共有八种类型:

int、float、bool、str、list、tuple、dict、None

JSON序列化支持这几种数据类型是因为JSON中就只支持这几种数据类型:

如下为python中的数据类型对应json中的数据类型;

python数据类型 JSON数据类型 int int float float bool(True,False) bool(true,false) None null str str(必须双引号) list([])、tuple(()) Array([]) dict({}) Object({})(键必须是双引号)

注意:

import json

dict_var = {1: 1, 2.2: 2.2, False: True, '123': '123', "234": "234", None: None}

json_obj = json.dumps(dict_var)
dict_var = json.loads(json_obj)

print(dict_var)
{'1': 1, '2.2': 2.2, 'false': True, '123': '123', '234': '234', 'null': None}

JSON可以序列化python八种数据, 序列化为字符串

pickle可以序列化python所有的数据类型, 序列化为字节流

JSON序列化函数和pickle的一样,名称和使用方法基本一样:

方法 含义 dumps 序列化 loads 反序列化 dump 序列化写入文件 load 读取文件反序列化

请注意以下几个序列化方法的常见参数:

[En]

Note here several common parameters of the serialization method:

ensure_asscii 默认为True, 以ACSII格式编码,以Unicode显示;
sort_keys 默认为True, 对字典的键进行排序;
indent默认为None, json格式化默认是一行不加缩进的,如果indent是一个正整数,就以该缩进级别进行换行,增强可视化。

import json

开启排序
dict_var = {'B': '2', 'A': '1'}
print(dict_var)  # {'B': '2', 'A': '1'}
json_char = json.dumps(dict_var, ensure_ascii=False, sort_keys=True)
dict_var = json.loads(json_char)
print(dict_var)  # {'A': '1', 'B': '2'}

关闭排序
dict_var = {'B': '2', 'A': '1'}
print(dict_var)  # {'B': '2', 'A': '1'}
json_char = json.dumps(dict_var, ensure_ascii=False, sort_keys=False)
dict_var = json.loads(json_char)
print(dict_var)  # {'B': '2', 'A': '1'}

dump 也一样哦

在操作文件时:

[En]

When operating on a file:

  • json可以连续dump,但是不能连续load
  • pickle可以连续dump和load

如下解释:

json 可以连续dump,但是不能连续load
import json

序列化数据
lst1 = [1, 2, 3]
lst2 = [4, 5, 6]
lst3 = [7, 8, 9]

序列化写入文件
with open('test.json', 'w', encoding='UTF-8') as fp:
    json.dump(lst1, fp)
    json.dump(lst2, fp)
    json.dump(lst3, fp)

读取文件反序列化
with open('test.json', 'r', encoding='UTF-8') as fp:
    data1 = json.load(fp)  # ERROR
    data2 = json.load(fp)
    data3 = json.load(fp)

!!! json.decoder.JSONDecodeError: Extra data: line 1 column 10 (char 9)

因为 json.dump 方法序列化写入文件的时候,写入了两个及以上的数据,之后 json.load 方法在读的时候又是一次性将整个文件中的数据读取出来,这个时候,反序列化的数据成了 [1, 2, 3][4, 5, 6][7, 8, 9] ,这明显不是一个json支持的数据格式,所以 json.load 失败了。

再来看pickle是怎么样的:

pickle 可以连续dump,也可以连续load
import pickle

序列化数据
lst1 = [1, 2, 3]
lst2 = [4, 5, 6]
lst3 = [7, 8, 9]

序列化写入文件
with open('pickle.txt', 'wb') as fp:
    pickle.dump(lst1, fp)
    pickle.dump(lst2, fp)
    pickle.dump(lst3, fp)

读取文件反序列化
with open('pickle.txt', 'rb') as fp:
    data1 = pickle.load(fp)  # [1, 2, 3]
    print(data1)
    data2 = pickle.load(fp)  # [4, 5, 6]
    print(data2)
    data3 = pickle.load(fp)  # [7, 8, 9]
    print(data3)

尝试在反序列化之前逐行阅读<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>Try to read line by line before deserializing</font>*</details>
with open('pickle.txt', 'rb') as fp:
    datum = fp.readlines()
    print(len(datum))  # 1

    for data in datum:
        data = pickle.loads(data)
        print(data)  # [1, 2, 3]   # 只能读出一个

可以看到 pickle.load 将数据都读出来了,这是因为 pickle.dump 在写入数据的时候在每条数据后都加上了一个标记(有些人解释说是换行,但是文件中并没有换行,逐行使用 fp.readlines 逐行读取的时候也只能获取一条,但是在文件中所有的数据都是在同一行的,我也不太懂了(无奈)),然后 pickle.load 每次就只会读一条数据,从IO指针读到每条数据后的那个标记为止,所以, pickle 可以连续的 load

怎么解决json的这个问题?

其实上面的这个问题,我个人认为是一种不规范的操作。因为 json.load 会一次性的读取整个文件中的内容,你却在一个文件中写入了不止一条的数据,那么在反序列化的时候当然会报错了。所以我认为:

json的主要作用多语言之前的数据传递和数据存储,每个JSON文件中最好只储存一条完整的数据。

但是我就想在一个json文件中存多个数据呢?

其实想法很简单,关键是读取文件然后反序列化,它必须是一块数据,一块数据反序列化,类似于:

[En]

In fact, the idea is very simple, the key is to read the file and then deserialize, it must be a piece of data, a piece of data deserialization, similar to the following:

import json

序列化数据
lst1 = [1, 2, 3]
lst2 = [4, 5, 6]
lst3 = [7, 8, 9]

串行化写入文件,为写入的每个数据插入一个换行符<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>Serialize writing to a file, inserting a newline for each piece of data written</font>*</details>
with open('test.json', 'w', encoding='UTF-8') as fp:
    json.dump(lst1, fp)
    fp.write('\n')
    json.dump(lst2, fp)
    fp.write('\n')
    json.dump(lst3, fp)

读取文件反序列化(逐行读取数据,然后反序列化)<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>Read file deserialization (read data line by line and then deserialize)</font>*</details>
with open('test.json', 'r', encoding='UTF-8') as fp:
    datum = fp.readlines()
    print(len(datum))  # 3

    for data in datum:
        data = json.loads(data)
        print(data)  # [1, 2, 3]
                     # [4, 5, 6]
                     # [7, 8, 9]

Original: https://www.cnblogs.com/msr20666/p/16308669.html
Author: 小小垂髫
Title: Python常用标准库(pickle序列化和JSON序列化)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/499499/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球