python基礎教程:序列化

上一節咱們學習了文件的讀寫,把一個字符串(或字節對象)保存到磁盤是一件很容易的事情。可是在實際編程中,咱們常常須要保存結構化數據,好比複雜的字典、嵌套的列表等等,這時候就須要咱們想辦法把這些結構化數據先轉變成一個字符串,這個轉換過程就叫作「序列化」,這一過程的逆操做就是「反序列化」。程序員

JSON序列化

序列化數據的操做在各個語言編程中都會遇到,固然也出現了標準化的格式,好比:JSON(JavaScript Object Notation)。JSON格式一般被現代應用程序用於數據交換,尤爲是在Web中廣爲人知,是許多程序員的選擇。Python支持JSON的模塊叫作json編程

JSON的數據格式和Python中的字典和列表很是類似,能夠說它是字典和列表相互嵌套的結合體,而這些字典和列表的基本數據類型只能是:字符串、整數、浮點數、布爾型、None,不能是自定義的類等複雜對象。json

一個對象x能夠用一行簡單的代碼轉換成它對應的JSON字符串:安全

In [124]: import json

In [125]: json.dumps({'Tom': 23, 'Jim': 25, 'William': 21})
Out[125]: '{"Tom": 23, "Jim": 25, "William": 21}'

把JSON字符串反序列化爲Python對象的代碼也只有一行:函數

In [126]: json.loads('{"Tom": 23, "Jim": 25, "William": 21}')
Out[126]: {'Tom': 23, 'Jim': 25, 'William': 21}

dumps()方法有個變體叫作dump(),它是將對象序列化到文件中。若是f是一個文件對象,咱們能夠這樣操做:工具

json.dump(x, f)

對應的,從文件對象f中反序列化的操做就是:學習

x = json.load(f)

dumps()函數有不少參數可選,使咱們生成不一樣格式的JSON字符串,具體能夠在IPython中經過json.dumps?來查看。咱們能夠經過下面的例子來了解一下:編碼

(1)緊湊編碼
經過separators參數來實現:spa

In [130]: json.dumps({"Tom": 23, "Jim": 25, "William": 21}, separators=(',', ':'))
Out[130]: '{"Tom":23,"Jim":25,"William":21}'

(2)美化輸出
經過sort_keys, indent參數來實現:設計

In [132]: print(json.dumps({"Tom": 23, "Jim": 25, '9':3, '3': 10}, sort_keys=True, indent=4))
{
    "3": 10,
    "9": 3,
    "Jim": 25,
    "Tom": 23
}

(3)中文編碼
參數ensure_ascii默認爲True,會把中文等非ascii字符轉義:

In [133]: print(json.dumps({"小剛": 23, "小明": 25, '9':3, '3': 10}, sort_keys=True, indent=4))
{
    "3": 10,
    "9": 3,
    "\u5c0f\u521a": 23,
    "\u5c0f\u660e": 25
}

In [134]: print(json.dumps({"小剛": 23, "小明": 25, '9':3, '3': 10}, sort_keys=True, indent=4, ensure_ascii=False))
{
    "3": 10,
    "9": 3,
    "小剛": 23,
    "小明": 25
}

pickle模塊序列化

json模塊不一樣,pickle能夠對任意複雜的Python對象進行序列化,它是Python特有的,不能與其它語言進行通訊。默認狀況下,它也是不安全的,若是數據是由黑客精心設計的,則反序列化的數據可能被植入惡意代碼。

pickle的接口跟json是同樣的,序列化用dumps(x), dump(x, f),反序列化使用loads(s), load(f)。可是,pickle能夠序列化任意複雜的對象,好比自定義的類、函數都是能夠用它來序列化的。好比下面這個例子就是序列化b並反序列化一個函數:

In [136]: def add(x, y): 
     ...:     print(x+y) 
     ...:

In [137]: import pickle

In [138]: s = pickle.dumps(add)

In [139]: s
Out[139]: b'\x80\x03c__main__\nadd\nq\x00.'

In [140]: f = pickle.loads(s)

In [141]: f
Out[141]: <function __main__.add(x, y)>

In [142]: f(2, 3)
5

從這個例子中,咱們實現了序列化和反序列化一個函數的功能。這樣,咱們能夠把一些函數、自定義的類等各類對象先序列化到文件,而後把這個文件發給別人,別人能夠經過反序列化來使用這些自定義的類和函數。這個過程當中,若是有人對序列化文件作了手腳,好比經過修改文件修改了函數add()的實現,就有可能被黑客利用來進行攻擊。這也是前面咱們爲何說pickle默認是不安全的。因此,在選擇是否使用它進行序列化時,要先思考一番。

總結

Python爲咱們提供了數據序列化的工具。若是須要和其它程序進行數據交換,json是最好的選擇。若是是本身內部使用,pickle能夠做爲一個選擇進行復雜對象的序列化。

相關文章
相關標籤/搜索