python读取序列5之后的数据_Python 基本功: 5. 数据序列化
這篇文章緊接著前篇:多多教Python:Python 基本功: 4. 讀寫文件?zhuanlan.zhihu.com
仔細(xì)閱讀的小伙伴會(huì)發(fā)現(xiàn),在基本功4 里最后的一個(gè)示例中,我們讀取解析了文件中的內(nèi)容,并且把其中的日期,價(jià)格金融數(shù)據(jù)存入了 Python 字典當(dāng)中:
In[4] abc_dict
Out[4]:{datetime.datetime(2019, 7, 18, 0, 0): 9682.24,
datetime.datetime(2019, 7, 17, 0, 0): 9411.61,
datetime.datetime(2019, 7, 16, 0, 0): 10858.7,
datetime.datetime(2019, 7, 15, 0, 0): 10195.0,
datetime.datetime(2019, 7, 14, 0, 0): 11378.23,
datetime.datetime(2019, 7, 13, 0, 0): 11810.0,
datetime.datetime(2019, 7, 12, 0, 0): 11338.9,
datetime.datetime(2019, 7, 11, 0, 0): 12090.99,
datetime.datetime(2019, 7, 10, 0, 0): 12577.85}
我們知道了如何從文章讀取數(shù)據(jù),解析,保存 (原數(shù)據(jù)),但是我們?cè)撊绾伪4?abc_dict 這個(gè)字典呢?這篇文章通過(guò)對(duì)數(shù)據(jù)的序列化,和其更高層次的應(yīng)用,來(lái)了解我們?nèi)绾握_的對(duì) Python 數(shù)據(jù)類做存儲(chǔ)。
教程需求:Mac OS (Windows, Linux 會(huì)略有不同)
安裝了 Python 3.0 版本以上, Anaconda
數(shù)據(jù)序列化
首先我們來(lái)了解一下什么是數(shù)據(jù)序列化。序列化 (Serialization),是指把程序中的一個(gè)類轉(zhuǎn)化成一個(gè)標(biāo)準(zhǔn)化的格式。標(biāo)準(zhǔn)化的意義是這個(gè)格式可以跨程序,跨平臺(tái)的被使用,而且保持其原有的內(nèi)容,規(guī)范。
首先我們舉個(gè)例子,在不用數(shù)據(jù)序列化的方法,而是直接把字典 abc_dict 存入文件,則是下面的情況:
In [1]:save_file = "abc_dict.txt"
In [2]:with open(save_file, 'w') as file_to_write:
file_to_write.write(str(abc_dict))創(chuàng)建一個(gè)變量,定義要存入文件名稱。
首先把字典轉(zhuǎn)化成 Python 基礎(chǔ)字符串,因?yàn)樽值浔旧聿荒苤苯颖粚懭胛募?#xff0c;然后再把字符串寫入文件中。
運(yùn)行之后,我們會(huì)在本地找到一個(gè)新的文件,如果你打開的話就是這樣:abc_dict.txt
我們來(lái)專業(yè)的分析一下這么做的幾個(gè)問(wèn)題:一致性:保存在文件的是一個(gè)字符串,當(dāng)你再次讀取的時(shí)候,你需要再次做文件解析,并且沒(méi)有任何保證解析出來(lái)的和保存的內(nèi)容是一樣的。
有效性:數(shù)據(jù)非常冗長(zhǎng),原本日期 7/18/2019 變成了 datetime.datetime(2019, 7, 18, 0, 0) 這么一個(gè)字符串。在跨平臺(tái)使用時(shí),占用了過(guò)多的內(nèi)存和網(wǎng)絡(luò)資源。
兼容性:文件是 .txt 格式,沒(méi)有一個(gè)標(biāo)準(zhǔn)來(lái)定義該如何讀取里面的內(nèi)容。雖然在寫入的時(shí)候是 Python 字典轉(zhuǎn)化的,但是讀取的程序如果不是 Python,或者不存入字典,就會(huì)出現(xiàn) 兼容性問(wèn)題。
保持?jǐn)?shù)據(jù)傳輸?shù)?一致性,有效性,兼容性 就是數(shù)據(jù)序列化的意義,下面介紹在數(shù)據(jù)流 (Data Flow)中,兩個(gè)數(shù)據(jù)序列化的應(yīng)用:你的程序需要和其他程序交流,例如 平臺(tái) API, 網(wǎng)頁(yè)請(qǐng)求串行任務(wù)流,每一個(gè)任務(wù)結(jié)束之后數(shù)據(jù)通過(guò)序列化傳遞到下一個(gè)任務(wù)。
JSON 序列化
這里我們來(lái)介紹第一個(gè)序列化方式:JSON。JSON 是一個(gè)文件格式,也是一個(gè)標(biāo)準(zhǔn)化的數(shù)據(jù)傳輸方案,通常網(wǎng)站的后端和前段的交流,移動(dòng) APP 和云服務(wù)器的交流方式都是通過(guò) JSON。所以我們先來(lái)看這個(gè)比較通用流行的方法:
In [1]:import json
In [2]:simple_dict = {'ticker': 'baba', 'price': '120.5'}
In [3]:with open('simple_dict.txt', 'w') as file_to_write:
json.dump(simple_dict, file_to_write)第一行調(diào)用了 Json 模塊 (模塊是較小的庫(kù),可以理解為子庫(kù)),Json 不是一個(gè) Python 自帶的基本類型,所以需要調(diào)用,但是默認(rèn)都已經(jīng)裝好了。
創(chuàng)建一個(gè)簡(jiǎn)單字典。
用同樣的方法 With 語(yǔ)境,創(chuàng)建一個(gè) simple_dict.txt 文件來(lái)保存數(shù)據(jù),然后通過(guò)調(diào)用 json.dump() 方法,把字典轉(zhuǎn)化成 Json 格式的字符串,然后寫進(jìn)文件。
現(xiàn)在我們打開 simple_dict.txt 的文件,就可以看到里面的數(shù)據(jù)是通過(guò) Json 格式保存。你可以建立一個(gè)更加復(fù)雜的字典來(lái)更加明了的發(fā)現(xiàn) Json 格式轉(zhuǎn)化后的區(qū)別:
In [1]: complex_dict = {'ticker': ['baba', 'pdd'], 'price': {'open': 120, 'close': 123, 'vwap': 122}}
然后用同樣的方法保存,打開保存的文件,復(fù)制里面的內(nèi)容,然后進(jìn)入:Json Parser Online?json.parser.online.fr
一個(gè) Json 在線解析網(wǎng)站,黏貼 Json 內(nèi)容,就會(huì)發(fā)現(xiàn)解析過(guò)后的字符串顯示的非常清晰。
從 Python 中讀取我們保存下來(lái)的 simple_dict 很簡(jiǎn)單,只需要一行代碼:
In [1]:with open('simple_dict.txt', 'r') as file_to_read:
loaded_simple_dict = json.load(file_to_read)
print(type(loaded_simple_dict))
Out [1]: json.load() 是直接從文件中讀取全部字符串,然后轉(zhuǎn)化成 Json 理解的格式,然后傳給變量 loaded simple dict。看了一下這個(gè)變量,的確是字典類。
那 Json 方法有什么弊端呢?嘗試把之前創(chuàng)建的 abc_dict 這個(gè)字典用同樣的方法保存進(jìn)文件中,你們會(huì)發(fā)現(xiàn) Python 會(huì)報(bào)錯(cuò):
這個(gè)錯(cuò)是因?yàn)?abc_dict 字典里的 鑰匙是 Python 的 Datetime 數(shù)據(jù)類,而 Json 的標(biāo)準(zhǔn)化里面并沒(méi)有 Python 的 Datetime 規(guī)則,也就是說(shuō)當(dāng)遇到一些 Python 特定的高級(jí)數(shù)據(jù)類型的時(shí)候,Json 會(huì)因?yàn)闆](méi)有標(biāo)準(zhǔn)而無(wú)法進(jìn)行序列化,而接下來(lái)介紹的這個(gè)工具會(huì)解決這個(gè)問(wèn)題。
Pickle 序列化
Pickle 和 Json 不同的是,Pickle 是 Python 專屬的序列化方案,可以轉(zhuǎn)化大多數(shù) Python 的數(shù)據(jù)類型,并且儲(chǔ)存方式是二進(jìn)制(Byte Code)。二進(jìn)制的儲(chǔ)存方式只有機(jī)器才能理解,但是同時(shí)也保證了一定的數(shù)據(jù)隱秘性和高效性。
下面我們來(lái)看如何用 Pickle 來(lái)實(shí)現(xiàn)數(shù)據(jù)序列化:
In [1]:import pickle
In [2]:with open('abc.pk', 'wb') as file_to_write:
pickle.dump(abc_dict, file_to_write)
In [3]:with open('abc.pk', 'rb') as file_to_read:
abc_dict_pk = pickle.load(file_to_read)
print(type(abc_dict_pk))
Out [3]:調(diào)用 Pickle 模塊。
這里打開文件的方式是 'wb', 因?yàn)?pickle 寫入的是二進(jìn)制格式,如果不加上 'b' 的話會(huì)導(dǎo)致無(wú)法寫入文件。
寫入文件之后,再用 pickle 讀出數(shù)據(jù),同樣的因?yàn)樽x取的是二進(jìn)制,我們用了 'rb' 模式。然后我們檢查返回的數(shù)據(jù)是否是字典類。
我們會(huì)發(fā)現(xiàn) Pickle 的語(yǔ)法和 Json 非常相似,雖然本身兩者對(duì)數(shù)據(jù)序列化的處理方式皆然不同,但是得益于 Python 的高級(jí)接口抽象(Interface Abstraction),記得 鴨子類型:
我們并不關(guān)心對(duì)象是什么類型,到底是不是鴨子,只關(guān)心行為。
這里兩個(gè)方法的行為都是在序列化數(shù)據(jù),所以在調(diào)用方程上感覺完全一樣。但是本質(zhì)上 Json 寫入文件的是字符串,而 Pickle 則是把數(shù)據(jù)轉(zhuǎn)化成了二進(jìn)制,兩個(gè)是完全不同的處理方案。
小結(jié)
現(xiàn)在流行的數(shù)據(jù)序列化方案還有 Protobuf, 一個(gè)谷歌開發(fā)的快速輕量級(jí)方案:protocolbuffers/protobuf?github.com
另一個(gè)是結(jié)合了Json 和 二進(jìn)制優(yōu)勢(shì)的 Bson:BSON (Binary JSON) Serialization?bsonspec.org
在一個(gè)大數(shù)據(jù)任務(wù)當(dāng)中,通常需要多任務(wù)并行和串行結(jié)合運(yùn)算加快速度。為了防止中間一環(huán)失敗而導(dǎo)致整個(gè)任務(wù)重啟,往往會(huì)在中間步驟把數(shù)據(jù)保存下來(lái),就像下圖:Map Reduce 利用 Transient Data (臨時(shí)數(shù)據(jù)) 來(lái)做進(jìn)度保存
在之后的課程中,Json 和 Pickle 都會(huì)頻繁的用到的領(lǐng)域有:大數(shù)據(jù)處理,消費(fèi)者數(shù)據(jù)流。
高并發(fā)的科學(xué)計(jì)算。
建立一個(gè)神經(jīng)網(wǎng)絡(luò)。
總結(jié)
以上是生活随笔為你收集整理的python读取序列5之后的数据_Python 基本功: 5. 数据序列化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 统计学习:基本常用公式(1)
- 下一篇: Python练习:tkinter(1)