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