python常用模組:json&pickle
之前我們學習過用eval內建方法可以將一個字串轉成python物件,不過,eval方法是有侷限性的,對於普通的資料型別,json.loads和eval都能用,但遇到特殊型別的時候,eval就不管用了,所以eval的重點還是通常用來執行一個字串表示式,並返回表示式的值
一、序列化
我們把物件(變數)從記憶體中變成可儲存或傳輸的過程稱之為序列化,在Python中叫pickling,在其他語言中也被稱之為serialization,marshalling,flattening等等,都是一個意思
二、為什麼要序列化
1:持久儲存狀態需知一個軟體/程式的執行就在處理一系列狀態的變化,在程式語言中,'狀態'會以各種各樣有結構的資料型別(也可簡單的理解為變數)的形式被儲存在記憶體中。記憶體是無法永久儲存資料的,當 程式運行了一段時間,我們斷電或者重啟程式,記憶體中關於這個程式的之前一段時間的資料(有結構)都被清空了。在斷電或重啟程式之前將程式當前記憶體中所有的資料都儲存下來(儲存到檔案中),以便於下次程式執行能夠從檔案中載入之前的資料,然後繼續執行,這就是序列化。具體的來說,你玩使命召喚闖到了第13關,你儲存遊戲狀態,關機走人,下次再玩,還能從上次的位置開始繼續闖關。或如,虛擬機器狀態的掛起等。
2:跨平臺資料互動序列化之後,不僅可以把序列化後的內容寫入磁碟,還可以通過網路傳輸到別的機器上,如果收發的雙方約定好實用一種序列化的格式,那麼便打破了平臺/語言差異化帶來的限制,實現了跨平臺資料互動。反過來,把變數內容從序列化的物件重新讀到記憶體裡稱之為反序列化,即unpickling。
三、json
如果我們要在不同的程式語言之間傳遞物件,就必須把物件序列化為標準格式,比如XML,但更好的方法是序列化為JSON,因為JSON表示出來就是一個字串,可以被所有語言讀取,也可以方便地儲存到磁碟或者通過網路傳輸。JSON不僅是標準格式,並且比XML更快,而且可以直接在Web頁面中讀取,非常方便。
import json dic={'name':'alvin','age':23,'sex':'male'} print(type(dic))#<class 'dict'> j=json.dumps(dic) print(type(j))#<class 'str'> f=open('序列化物件','w') f.write(j) #-------------------等價於json.dump(dic,f) f.close() #-----------------------------反序列化<br> import json f=open('序列化物件') data=json.loads(f.read())# 等價於data=json.load(f)
需要注意的地方
import json #dct="{'1':111}"#json 不認單引號 #dct=str({"1":111})#報錯,因為生成的資料還是單引號:{'one': 1} dct='{"1":"111"}' print(json.loads(dct)) #conclusion: # 無論資料是怎樣建立的,只要滿足json格式,就可以json.loads出來,不一定非要dumps的資料才能loads 注意點注意點
# 在python直譯器2.7與3.6之後都可以json.loads(bytes型別),但唯獨3.5不可以 >>> import json >>> json.loads(b'{"a":111}') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/linhaifeng/anaconda3/lib/python3.5/json/__init__.py", line 312, in loads s.__class__.__name__)) TypeError: the JSON object must be str, not 'bytes' 瞭解不同py版本的不同點
# 一.什麼是猴子補丁? 猴子補丁的核心就是用自己的程式碼替換所用模組的原始碼,詳細地如下 1,這個詞原來為Guerrilla Patch,雜牌軍、游擊隊,說明這部分不是原裝的,在英文裡guerilla發音和gorllia(猩猩)相似,再後來就寫了monkey(猴子)。 2,還有一種解釋是說由於這種方式將原來的程式碼弄亂了(messing with it),在英文裡叫monkeying about(頑皮的),所以叫做Monkey Patch。 # 二. 猴子補丁的功能(一切皆物件) 1.擁有在模組執行時替換的功能, 例如: 一個函式物件賦值給另外一個函式物件(把函式原本的執行的功能給替換了) class Monkey: def hello(self): print('hello') def world(self): print('world') def other_func(): print("from other_func") monkey = Monkey() monkey.hello = monkey.world monkey.hello() monkey.world = other_func monkey.world() # 三.monkey patch的應用場景 如果我們的程式中已經基於json模組編寫了大量程式碼了,發現有一個模組ujson比它效能更高, 但用法一樣,我們肯定不會想所有的程式碼都換成ujson.dumps或者ujson.loads,那我們可能 會想到這麼做 import ujson as json,但是這麼做的需要每個檔案都重新匯入一下,維護成本依然很高 此時我們就可以用到猴子補丁了 只需要在入口處加上 , 只需要在入口加上: import json import ujson def monkey_patch_json(): json.__name__ = 'ujson' json.dumps = ujson.dumps json.loads = ujson.loads monkey_patch_json() # 之所以在入口處加,是因為模組在匯入一次後,後續的匯入便直接引用第一次的成果 #其實這種場景也比較多, 比如我們引用團隊通用庫裡的一個模組, 又想豐富模組的功能, 除了繼承之外也可以考慮用Monkey Patch.採用猴子補丁之後,如果發現ujson不符合預期,那也可以快速撤掉補丁。個人感覺Monkey Patch帶了便利的同時也有搞亂原始碼的風險! 猴子補丁與ujson猴子補丁與ujson