大數據

序列化和反序列化

本文來自於千鋒教育在阿里雲開發者社區學習中心上線課程《Python入門2020最新大課》,主講人姜偉。

序列化和反序列化

通過⽂件操作,我們可以將字符串寫⼊到⼀個本地⽂件。但是,如果是⼀個對象(例如列表、字典、元組等),就⽆法直接寫⼊到⼀個⽂件⾥,需要對這個對象進⾏序列化,然後才能寫⼊到⽂件⾥。

設計⼀套協議,按照某種規則,把內存中的數據轉換為字節序列,保存到⽂件,這就是序列化,反之,從⽂件的字節序列恢復到內存中,就是反序列化。

Python中提供了JSON和pickle兩個模塊⽤來實現數據的序列化和反序列化。

JSON模塊

JSON(JavaScriptObjectNotation, JS對象簡譜)是⼀種輕量級的數據交換格式,它基於 ECMAScript 的⼀個⼦集,採⽤完全獨⽴於編程語⾔的⽂本格式來存儲和表示數據。JSON的本質是字符串!JSON裡要使用雙引號表示字符串。

使⽤JSON實現序列化

JSON提供了dump和dumps⽅法,將⼀個對象進⾏序列化。
dumps⽅法的作⽤是把對象轉換成為字符串,它本身不具備將數據寫⼊到⽂件的功能。

import json

file = open('names.txt', 'w')
names = ['zhangsan', 'lisi', 'wangwu', 'jerry', 'henry', 'merry', 'chris']
# file.write(names) 出錯,不能直接將列表寫⼊到⽂件⾥

# 可以調⽤ json的dumps⽅法,傳⼊⼀個對象參數
result = json.dumps(names)

# dumps ⽅法得到的結果是⼀個字符串
print(type(result)) # <class 'str'>

# 可以將字符串寫⼊到⽂件⾥
file.write(result)

file.close()

dump⽅法可以在將對象轉換成為字符串的同時,指定⼀個⽂件對象,把轉換後的字符串寫⼊到這個⽂件⾥。

import json

file = open('names.txt', 'w')
names = ['zhangsan', 'lisi', 'wangwu', 'jerry', 'henry', 'merry', 'chris']

# dump⽅法可以接收⼀個⽂件參數,在將對象轉換成為字符串的同時寫⼊到⽂件⾥
json.dump(names, file)
file.close()

注意:如果是⼀個空對象,調⽤dumps⽅法轉換成為⼀個JSON對象,得到的結果是null(JS⾥的空對象)

json.dumps(None) # null

使⽤JSON實現反序列化

使⽤loads和load⽅法,可以將⼀個JSON字符串反序列化成為⼀個Python對象。

loads⽅法需要⼀個字符串參數,⽤來將⼀個字符串加載成為Python對象。

import json

# 調⽤loads⽅法,傳⼊⼀個字符串,可以將這個字符串加載成為Python對象
result = json.loads('["zhangsan", "lisi", "wangwu", "jerry", "henry", "merry", "chris"]')
print(type(result)) # <class 'list'>

load⽅法可以傳⼊⼀個⽂件對象,⽤來將⼀個⽂件對象⾥的數據加載成為Python對象。

import json

# 以可讀⽅式打開⼀個⽂件
file = open('names.txt', 'r')

# 調⽤load⽅法,將⽂件⾥的內容加載成為⼀個Python對象
result = json.load(file)

print(result)
file.close()

pickle模塊

和json模塊類似,pickle模塊也有dump和dumps⽅法可以對數據進⾏序列化,同時也有load和loads⽅法進⾏反序列化。區別在於,json模塊是將對象轉換成為字符串,⽽pickle模塊是將對象轉換成為⼆進制。

pickle模塊⾥⽅法的使⽤和json⾥⽅法的使⽤⼤致相同,需要注意的是,pickle是將對象轉換成為⼆進制,所以,如果想要把內容寫⼊到⽂件⾥,這個⽂件必須要以⼆進制的形式打開。
序列化
dumps:將Python數據轉化為二進制
dump:將Python數據轉化為二進制,同時保存到指定文件

反序列化
loads:將二進制加載成為python數據
load:讀取文件,並將文件的二進制內容加載成為python數據

import pickle

names = ['張三', '李四', '傑克', '亨利']
b_names = pickle.dumps(names)

file  = open('names.txt', 'wb')
file.write(b_names)   # 寫入的是二進制
file.close()

file1 = open('names.txt', 'rb')
x = file1.read()
y = pickle.loads(x)
print(y)
file1.close()


file2 = open('names.txt', 'wb')
pickle.dump(names, file2)
file2.close()


file3 = open('names.txt', 'rb')
pickle.load(file3)
class Dog(object):
    def __init__(self, name, color):
        self.name = name
        self.color = color

     def eat(self):
        print(self.name + '正在吃東西')

d = Dog('大黃', '白色')

# 保存到文件裡
pickle.dump(d, open('dog.txt', 'wb'))

# 從文件里加載出來
dd = pickle.load(d, open('dog.txt', 'rb'))
dd.eat()  

print(dd.name, dd.color)   # 大黃 白色

區別

思考: json和pickle兩個模塊都可以將對象進⾏序列化和反序列化,那它們有哪些區別,在使⽤場景上⼜該如何選擇?

json模塊:

  • 將對象轉換成為字符串,不管是在哪種操作系統,哪種編程語⾔⾥,字符串都是可識別的。
  • json就是⽤來在不同平臺間傳遞數據的。
  • 並不是所有的對象都可以直接轉換成為⼀個字符串,下標列出了Python對象與json字符串的對應關係。

image.png

  • 如果是⼀個⾃定義對象,默認⽆法裝換成為json字符串,需要⼿動指定JSONEncoder。
  • 如果是將⼀個json串重新轉換成為對象,這個對象⾥的⽅法就⽆法使⽤了。
import json

class MyEncode(json.JSONEncoder):
    def default(self, o):
        # return {"name":o.name,"age":o.age}
        return o.__dict__

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self):
        print(self.name+'正在吃東⻄')

p1 = Person('zhangsan', 18)

# ⾃定義對象想要轉換成為json字符串,需要給這個⾃定義對象指定JSONEncoder
result = json.dumps(p1, cls=MyEncode)
print(result) # {"name": "zhangsan", "age": 18}

# 調⽤loads⽅法將對象加載成為⼀個對象以後,得到的結果是⼀個字典
p = json.loads(result)
print(type(p))

pickle模塊:

  • pickle序列化是將對象按照⼀定的規則轉換成為⼆進制保存,它不能跨平臺傳遞數據。
  • pickle的序列化會將對象的所有數據都保存。

配套視頻

Leave a Reply

Your email address will not be published. Required fields are marked *