欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python开发pickle和json序列化及json配置文件常见问题

程序员文章站 2024-01-04 14:46:16
在程序运行的过程中,变量都是在内存中,比如,定义一个dict:d = dict(name='rose', career='student', age='20')把变量从内存中变成可存储或传输的过程称之为序列化,反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化。picklepickle.dumps()方法把任意对象序列化成一个bytes,然后,就可以把这个bytes写入文件。用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object:impor...

在程序运行的过程中,变量都是在内存中,比如,定义一个dict:

d = dict(name='rose', career='student', age='20')

把变量从内存中变成可存储或传输的过程称之为序列化,
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化。

pickle

pickle.dumps()方法把任意对象序列化成一个bytes,然后,就可以把这个bytes写入文件。
用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object:

import pickle

d = dict(name='rose', career='student', age='20')
fp = open('dump.txt', 'wb')
pickle.dump(d, fp)
fp.close()

当我们要把对象从磁盘读到内存时,可以先把内容读到一个bytes,然后用pickle.loads()方法反序列化出对象
也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象。

fp = open('dump.txt', 'rb')
d = pickle.load(fp)
fp.close()
print(d)	# {'name': 'rose', 'career': 'student', 'age': 20}

变量的内容又回来了。

注意:使用pickle存取读取文件,一定要以二进制来读写

提出问题

这里我向大家提问一个问题,看到这里的伙伴可以回答我一下,征集一下看看有没有什么好的方法解决:
问:如果将多个dict存入到同一个文件,该如何处理?当然下面的json格式存储也可能需要回答这个问题,那么我会说明我在学习中json解决这个问题的一种方式(其实很简单啦),这也是我在做项目很喜欢使用的一种配置文件的方式。

json

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
Python内置的json模块提供了非常完善的Python对象到JSON格式的转换。

json中的dump和load方法实际是字符串和dict互转的方法,只是添加了将对象和dict互相转换的方法,才实现了将对象转换为json字符串。

如果要把对象以json格式存储,那么先要这个对象有一个把属性和属性值以键值对形式(dict)的表示方式,那么有两种方式可以实现转换dict方法。

  1. 使用对象的__dict__属性,它就是一个dict,用来存储实例变量。也有少数例外,比如定义了__slots__的class。如下方式将对象转换为json字符串的方式
import json


class Student(object):
	def __init__(self, name='rose', age=22, id='11111'):
        self.name = name
        self.age = age
        self.id = id

if __name__ == '__maini__':
	s1 = Student()
	print(type(s1.__dict__))		# dict
    print(json.dumps(s1.__dict__))
    print(type(json.dumps(s1.__dict__)))
  1. 自行定义一个对象转dict的方法,在调用json.dumps()加入这个方法作为default参数值,如下:
def student2dict(stu):
    return {
        'name': stu.name,
        'age': stu.age,
        'id': stu.id
    }

print(json.dumps(s1, default=student2dict))
# {"name": "rose", "age": 22, "id": "11111"}

同样的道理,如果我们要把JSON反序列化为一个Student对象实例,loads()方法首先转换出一个dict对象,然后,我们传入的object_hook函数负责把dict转换为Student实例

def dict2student(d):
    return Student(d['name'], d['age'], d['id'])

json_str = '{"name": "rose", "age": 22, "id": "11111"}'
d= json.loads(json_str)			# dict
s2 = json.loads(json_str, object_hook=dict2student)		# Student
多个对象以json格式读写文件

接下来说明把多个对象以json格式存入到文件中:
如下第一个方法将多个对象写入文件,写入一个对象为一行,然后会换行,
然后第二个方法是每次读取一行,然后将这一行json字符串转换为对象。

def write_Student_json(filepath, student_list):
    with open(filepath, 'w') as fp:
        for s in student_list:
            json.dump(s.__dict__, fp)
            fp.write('\n')


def get_students_from_file(filepath):
    student_list = []
    with open(filepath, 'r') as fp:
        for json_str in fp.readlines():
            s = json.loads(json_str, object_hook=dict2student)
            student_list.append(s)
    return student_list


if __name__ == '__main__':
	s1 = Student()
    s2 = Student('George', 30, '131313')
    s_l1 = [s1, s2]
    write_Student_json('student.txt', s_l1)

    s_l2 = get_students_from_file('student.txt')

    for s in s_l2:
        print(str(s.__dict__))

如下是写入的同文件夹下的student.txt文件

{"name": "rose", "age": 22, "id": "11111"}
{"name": "George", "age": 30, "id": "131313"}

注意问题

这里呢,是我最近在开发中遇见的两个问题,我最近在最初设计方案的时候,都会试着使用配置文件来调试,然后才会去设计将一些数据存入数据库……这是我在将多个对象存入json文件中遇到的问题,问题都是和文件相关,与也算是比较常见的了。
所以,我会提醒看到这的小伙伴,不要轻易改动json文件

  1. 字符串类型,使用json读取写入一律使用双引号
    因为我试着去编辑配置,然后就习惯的把字符串类型写成了单引号,然后就报了如下的异常:
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 29 (char 28)

所以,json文件中的字符串类型的引号要注意了

  1. 不要轻易多加换行
    因为我在查看配置文件的时候,不知道什么时候点了回车,导致json文件最后多了一个换行,就报了如下的异常:
json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)

所以如果在玩json文件的时候,尽量不要去改动,按照程序写入文件的格式即可。

本文地址:https://blog.csdn.net/qq_43909184/article/details/107114996

上一篇:

下一篇: