Python的數據序列化「Json & Pickle」
在介紹Python的數據序列化模塊「Json & Pickle」之前,我們先來看看為什么需要數據序列化,什么是數據序列化。
為什么需要數據序列化,我認為有如下兩種原因:
一個原因是將對象(一切皆對象)的狀態保持在存儲媒介(硬盤、網盤......)中,以便可以在以后重新創建精確的副本,相當于鏡像的概念,比如我們平時利用VMware虛擬機中的掛起功能,這個掛起功能就是利用數據的序列化,把虛擬機當前的狀態序列化保存在本地磁盤的文件中,然后恢復的時候只需反序列化,把狀態恢復即可。
另一個原因是通過值將對象從一個應用程序域發送到另一個應用程序域中。例如,你利用Python監控采集程序采集到的數據想傳送給Zabbix處理。當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個對象轉換為字節序列,才能在網絡上傳送;接收方則需要把字節序列再恢復為對象。
序列化和反序列化:
- 序列化: 將數據結構或對象轉換成二進制串的過程。
- 反序列化:將在序列化過程中所生成的二進制串轉換成數據結構或者對象的過程。
序列化的目的就是為了跨進程傳遞格式化數據和保存某個時刻的狀態。
什么是數據序列化:
數據序列化就是將對象或者數據結構轉化成特定的格式,使其可在網絡中傳輸,或者可存儲在內存或者文件中。反序列化則是相反的操作,將對象從序列化數據中還原出來。而對象序列化后的數據格式可以是二進制,可以是XML,也可以是JSON等任何格式。對象/數據序列化的重點在于數據的交換和傳輸,例如在遠程調用技術(如EJB,XML-RPC, Web Service),或者在GUI控件開發(JavaBean)等等。
清楚了數據格式化的必要和簡單認識了什么是數據格式化之后,我們就來看看Python中兩個數據格式化模塊的使用。
Json Module
Json:用于字符串和 python數據類型間進行轉換;
Json模塊提供了四個功能:dumps、dump、loads、load
1.dumps把數據類型轉換成字符串
2.dump把數據類型轉換成字符串并存儲在文件中
3.loads把字符串轉換成數據類型
4.load把文件打開從字符串轉換成數據類型
實例如下:
- #!/usr/bin/env python3
- # _*_coding:utf-8_*_
- # Author: Lucky.chen
- import json
- info = {'1MinLoad': 5, 'MemUse': '5G', 'DiskUse': '80G'}
- print('dumps 操作之前數據類型: %s' % type(info))
- JsonInfo = json.dumps(info)
- print(JsonInfo)
- # dumps 將數據通過特殊的形式轉換為所有程序語言都識別的字符串
- print('dumps 操作之后數據類型: %s' % type(JsonInfo))
- # loads 將字符串通過特殊的形式轉為python是數據類型 (將字符串轉為字典)
- NewInfo = json.loads(JsonInfo)
- print('loads 操作之后數據類型為: %s' % type(NewInfo))
- print('分割線'.center(50, '-'))
- # dump 將數據通過特殊的形式轉換為所有語言都識別的字符串并寫入文件
- with open('SystemInfo.txt', 'w') as f:
- json.dump(info, f)
- print('dump file end!!')
- # load 從文件讀取字符串并轉換為python的數據類型
- with open('SystemInfo.txt', 'r') as f:
- LoadInfo = json.load(f)
- print('load file end, data type is %s' % type(LoadInfo), LoadInfo)
結果如下:
- dumps 操作之前數據類型: <class 'dict'>
- {"MemUse": "5G", "DiskUse": "80G", "1MinLoad": 5}
- dumps 操作之后數據類型: <class 'str'>
- loads 操作之后數據類型為: <class 'dict'>
- -----------------------分割線------------------------
- dump file end!!
- load file end, data type is <class 'dict'> {'MemUse': '5G', '1MinLoad': 5, 'DiskUse'
一個錯誤案例如下:
- #!/usr/bin/env python3
- # _*_coding:utf-8_*_
- # Author: Lucky.chen
- import json
- def test():
- print('Test Func')
- info = {'Name': 'crh', 'age': 18, 'Func': test}
- json.dumps(info)
結果:
- raise TypeError(repr(o) + " is not JSON serializable")
- ypeError: <function test at 0x108e7a0d0> is not JSON serializable
如上可知函數不能被json序列化。
Pickle Module
pickle,用于python特有的類型 和 python的數據類型間進行轉換
Pickle模塊同樣提供了四個功能:dumps、dump、loads、load
1.dumps把數據類型轉換成字符串
2.dump把數據類型轉換成字符串并存儲在文件中
3.oads把字符串轉換成數據類型
4.load把文件打開從字符串轉換成數據類型
Pickle可以序列化一些較復雜的數據,和json的區別在于pickle序列化的時候,存放的是二進制的文件,所以打開一個文件的時候,我們要以二進制的格式打開。
實例如下:
- #!/usr/bin/env python3
- # _*_coding:utf-8_*_
- # Author: Lucky.chen
- import pickle
- def test(name):
- print('%s write Test Func' % name)
- info = {'Name': 'crh', 'age': 18, 'Func': test}
- print('dumps 之前數據的類型為: %s' % type(info))
- # pickle.dumps 將數據通過特殊的形式轉換為只有python語言認識bytes類型(Python2.*中是字符串類型)
- NewInfo = pickle.dumps(info)
- print('dumps result is %s, data type is %s' % (NewInfo, type(NewInfo)))
- # pickle.loads 將bytes通過特殊的形式轉為python是數據類型
- LoadInfo = pickle.loads(NewInfo)
- print('loads result is %s, data type is %s' % (LoadInfo, type(LoadInfo)))
- LoadInfo['Func']('crh')
- print('分割線'.center(50, '-'))
- # pickle.dump 將數據通過特殊的形式轉換為只有python語言認識的字符串,并寫入文件
- with open('pickle.rb', 'wb') as f:
- pickle.dump(info, f)
- # pickle.load 從文件讀取只有python語言認識的字符串并轉換為python的數據類型
- with open('pickle.rb', 'rb') as f:
- Info = pickle.load(f)
- print(Info, 'type is %s' % type(Info))
結果如下:
- dumps 之前數據的類型為: <class 'dict'>
- dumps result is b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x12X\x04\x00\x00\x00Nameq\x02X\x03\x00\x00\x00crhq\x03X\x04\x00\x00\x00Funcq\x04c__main__\ntest\nq\x05u.', data type is <class 'bytes'>
- loads result is {'age': 18, 'Name': 'crh', 'Func': <function test at 0x1032f10d0>}, data type is <class 'dict'>
- crh write Test Func
- -----------------------分割線------------------------
- {'age': 18, 'Name': 'crh', 'Func': <function test at 0x1032f10d0>} type is <class 'di
總結
很多情況下不同的程序之間傳送數據我們一般通過文件的方式,但是這個方法是最原始的,而dumps可以直接讓數據格式化傳送給對方,但是不是所有的程序都是python的,所以只利用pickle是不現實的,比如一個python的程序需要發送一段數據給一個java程序開發的應用,這時候很多內存數據的交換,就得用json了。
并且josn能dump的結果更可讀,那么有人就問了,那還用pickle做什么不直接用josn,是這樣的josn只能把常用的數據類型序列化(列表、字典、列表、字符串、數字、),比如日期格式、類對象!josn就不行了。
為什么他不能序列化上面的東西呢?因為josn是跨語言的!注定了它只能規范出一些通用的數據類型的格式,統一標準。