這篇文章主要為大家展示了“Python中常見(jiàn)序列化操作的示例分析”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Python中常見(jiàn)序列化操作的示例分析”這篇文章吧。
錦江ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書(shū)銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書(shū)合作)期待與您的合作!0x00 marshal
marshal使用的是與Python語(yǔ)言相關(guān)但與機(jī)器無(wú)關(guān)的二進(jìn)制來(lái)讀寫(xiě)Python對(duì)象的。這種二進(jìn)制的格式也跟Python語(yǔ)言的版本相關(guān),marshal序列化的格式對(duì)不同的版本的Python是不兼容的。
marshal一般用于Python內(nèi)部對(duì)象的序列化。
一般地包括:
基本類型 booleans, integers,floating point numbers,complex numbers
序列集合類型 strings, bytes, bytearray, tuple, list, set, frozenset, dictionary
code對(duì)象 code object
其它類型 None, Ellipsis, StopIteration
marshal的主要作用是對(duì)Python“編譯”的.pyc文件讀寫(xiě)的支持。這也是marshal對(duì)Python版本不兼容的原因。開(kāi)發(fā)者如果要使用序列化/反序列化,那么應(yīng)該使用pickle模塊。
常見(jiàn)的方法
marshal.dump(value, file[, version])
序列化一個(gè)對(duì)象到文件中
marshal.dumps(value[, version])
序列化一個(gè)對(duì)象并返回一個(gè)bytes對(duì)象
marshal.load(file)
從文件中反序列化一個(gè)對(duì)象
marshal.loads(bytes)
從bytes二進(jìn)制數(shù)據(jù)中反序列化一個(gè)對(duì)象
0x01 pickle
pickle模塊也能夠以二進(jìn)制的方式對(duì)Python對(duì)象進(jìn)行讀寫(xiě)。相比marshal提供基本的序列化能力,pickle的序列化應(yīng)用更加廣泛。
pickle序列化后的數(shù)據(jù)也是與Python語(yǔ)言相關(guān)的,即其它語(yǔ)言例如Java無(wú)法讀取由Python通過(guò)pickle序列化的二進(jìn)制數(shù)據(jù)。如果要使用與語(yǔ)言無(wú)法的序列化那么我們應(yīng)該使用json。下文將會(huì)說(shuō)明。
能被pickle序列化的數(shù)據(jù)類型有:
None, True, and False
integers, floating point numbers, complex numbers
strings, bytes, bytearrays
tuples, lists, sets, and dictionaries 以及包含可以被pickle序列化對(duì)象
在模塊頂層定義的函數(shù)對(duì)象 (使用 def定義的, 而不是 lambda表達(dá)式)
在模塊頂層定義內(nèi)置函數(shù)
在模式頂層定義的類
一個(gè)類的__dict__包含了可序列化的對(duì)象或__getstate__()方法返回了能夠被序列化的對(duì)象
如果pickle一個(gè)不支持序列化的對(duì)象時(shí)將會(huì)拋出PicklingError。
常見(jiàn)的方法
pickle.dump(obj, file, protocol=None, *, fix_imports=True)
將obj對(duì)象序列化到一個(gè)file文件中,該方法與Pickler(file, protocol).dump(obj)等價(jià)。
pickle.dumps(obj, protocol=None, *, fix_imports=True)
將obj對(duì)象序列化成bytes二進(jìn)制數(shù)據(jù)。
pickle.load(file, *, fix_imports=True, encoding="ASCII", errors="strict")
從file文件中反序列化一個(gè)對(duì)象,該方法與Unpickler(file).load()等價(jià)。
pickle.loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")
從二進(jìn)制數(shù)據(jù)bytes_object反序列化對(duì)象。
序列化例子
import pickle # 定義了一個(gè)包含了可以被序列化對(duì)象的字典 data = { 'a': [1, 2.0, 3, 4 + 6j], 'b': ("character string", b"byte string"), 'c': {None, True, False} } with open('data.pickle', 'wb') as f: # 序列化對(duì)象到一個(gè)data.pickle文件中 # 指定了序列化格式的版本pickle.HIGHEST_PROTOCOL pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)
執(zhí)行之后在文件夾中多一個(gè)data.pickle文件
serialization
├── data.pickle
├── pickles.py
└── unpickles.py
反序列化例子
import pickle with open('data.pickle', 'rb') as f: # 從data.pickle文件中反序列化對(duì)象 # pickle能夠自動(dòng)檢測(cè)序列化文件的版本 # 所以這里可以不用版本號(hào) data = pickle.load(f) print(data) # 執(zhí)行后結(jié)果 # {'a': [1, 2.0, 3, (4+6j)], 'b': ('character string', b'byte string'), 'c': {False, True, None}}
0x02 json
json是與語(yǔ)言無(wú)關(guān),非常通用的數(shù)據(jù)交互格式。在Python它與marshal和pickle一樣擁有相似的API。
常見(jiàn)的方法
json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
序列化對(duì)象到fp文件中
json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
將obj序列化成json對(duì)象
json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
從文件中反序列化成一個(gè)對(duì)象
json.loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
從json格式文檔中反序列化成一個(gè)對(duì)象
json與Python對(duì)象的轉(zhuǎn)化對(duì)照表
JSON | Python |
---|---|
object | dict |
list,tuple | array |
str | string |
int, float, int- & float-derived Enums | number |
True | true |
False | false |
None | null |
對(duì)于基本類型、序列、以及包含基本類型的集合類型json都可以很好的完成序列化工作。
序列化例子
>>> import json >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}]) '["foo", {"bar": ["baz", null, 1.0, 2]}]' >>> print(json.dumps("\"foo\bar")) "\"foo\bar" >>> print(json.dumps('\u1234')) "\u1234" >>> print(json.dumps('\\')) "\\" >>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)) {"a": 0, "b": 0, "c": 0} >>> from io import StringIO >>> io = StringIO() >>> json.dump(['streaming API'], io) >>> io.getvalue() '["streaming API"]'
反序列化例子
>>> import json >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') ['foo', {'bar': ['baz', None, 1.0, 2]}] >>> json.loads('"\\"foo\\bar"') '"foo\x08ar' >>> from io import StringIO >>> io = StringIO('["streaming API"]') >>> json.load(io) ['streaming API']
對(duì)于object的情況就復(fù)雜一些了
例如定義了復(fù)數(shù)complex對(duì)象的json文檔
complex_data.json
{ "__complex__": true, "real": 42, "imaginary": 36 }
要把這個(gè)json文檔反序列化成Python對(duì)象,就需要定義轉(zhuǎn)化的方法
# coding=utf-8 import json # 定義轉(zhuǎn)化函數(shù),將json中的內(nèi)容轉(zhuǎn)化成complex對(duì)象 def decode_complex(dct): if "__complex__" in dct: return complex(dct["real"], dct["imaginary"]) else: return dct if __name__ == '__main__': with open("complex_data.json") as complex_data: # object_hook指定轉(zhuǎn)化的函數(shù) z = json.load(complex_data, object_hook=decode_complex) print(type(z)) print(z) # 執(zhí)行結(jié)果 # <class 'complex'> # (42+36j)
如果不指定object_hook,那么默認(rèn)將json文檔中的object轉(zhuǎn)成dict
# coding=utf-8 import json if __name__ == '__main__': with open("complex_data.json") as complex_data: # 這里不指定object_hook z2 = json.loads(complex_data.read()) print(type(z2)) print(z2) # 執(zhí)行結(jié)果 # <class 'dict'> # {'__complex__': True, 'real': 42, 'imaginary': 36}
可以看到j(luò)son文檔中的object轉(zhuǎn)成了dict對(duì)象。
一般情況下這樣使用似乎也沒(méi)什么問(wèn)題,但如果對(duì)類型要求很高的場(chǎng)景就需要明確定義轉(zhuǎn)化的方法了。
除了object_hook參數(shù)還可以使用json.JSONEncoder
import json class ComplexEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, complex): # 如果complex對(duì)象這里轉(zhuǎn)成數(shù)組的形式 return [obj.real, obj.imag] # 默認(rèn)處理 return json.JSONEncoder.default(self, obj) if __name__ == '__main__': c = json.dumps(2 + 1j, cls=ComplexEncoder) print(type(c)) print(c) # 執(zhí)行結(jié)果 # <class 'str'> # [2.0, 1.0]
因?yàn)閖son模塊并不是對(duì)所有類型都能夠自動(dòng)完成序列化的,對(duì)于不支持的類型,會(huì)直接拋出TypeError。
>>> import datetime >>> d = datetime.datetime.now() >>> dct = {'birthday':d,'uid':124,'name':'jack'} >>> dct {'birthday': datetime.datetime(2019, 6, 14, 11, 16, 17, 434361), 'uid': 124, 'name': 'jack'} >>> json.dumps(dct) Traceback (most recent call last): File "<pyshell#19>", line 1, in <module> json.dumps(dct) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 231, in dumps return _default_encoder.encode(obj) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 179, in default raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type datetime is not JSON serializable
對(duì)于不支持序列化的類型例如datetime以及自定義類型,就需要使用JSONEncoder來(lái)定義轉(zhuǎn)化的邏輯。
import json import datetime # 定義日期類型的JSONEncoder class DatetimeEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime.datetime): return obj.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(obj, datetime.date): return obj.strftime('%Y-%m-%d') else: return json.JSONEncoder.default(self, obj) if __name__ == '__main__': d = datetime.date.today() dct = {"birthday": d, "name": "jack"} data = json.dumps(dct, cls=DatetimeEncoder) print(data) # 執(zhí)行結(jié)果 # {"birthday": "2019-06-14", "name": "jack"}
現(xiàn)在我們希望發(fā)序列化時(shí),能夠?qū)son文檔中的日期格式轉(zhuǎn)化成datetime.date對(duì)象,這時(shí)就需要使用到j(luò)son.JSONDecoder了。
# coding=utf-8 import json import datetime # 定義Decoder解析json class DatetimeDecoder(json.JSONDecoder): # 構(gòu)造方法 def __init__(self): super().__init__(object_hook=self.dict2obj) def dict2obj(self, d): if isinstance(d, dict): for k in d: if isinstance(d[k], str): # 對(duì)日期格式進(jìn)行解析,生成一個(gè)date對(duì)象 dat = d[k].split("-") if len(dat) == 3: date = datetime.date(int(dat[0]), int(dat[1]), int(dat[2])) d[k] = date return d if __name__ == '__main__': d = datetime.date.today() dct = {"birthday": d, "name": "jack"} data = json.dumps(dct, cls=DatetimeEncoder) # print(data) obj = json.loads(data, cls=DatetimeDecoder) print(type(obj)) print(obj) # 執(zhí)行結(jié)果 # {"birthday": "2019-06-14", "name": "jack"} # <class 'dict'> # {'birthday': datetime.date(2019, 6, 14), 'name': 'jack'}
0x03 總結(jié)一下
Python常見(jiàn)的序列化工具有marshal、pickle和json。marshal主要用于Python的.pyc文件,并與Python版本相關(guān)。它不能序列化用戶定義的類。
pickle是Python對(duì)象的序列化工具則比marshal更通用些,它可以兼容Python的不同版本。json是一種語(yǔ)言無(wú)關(guān)的數(shù)據(jù)結(jié)構(gòu),廣泛用于各種網(wǎng)絡(luò)應(yīng)用尤其在REST API的服務(wù)中的數(shù)據(jù)交互。
以上是“Python中常見(jiàn)序列化操作的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
文章標(biāo)題:Python中常見(jiàn)序列化操作的示例分析-創(chuàng)新互聯(lián)
文章分享:http://m.newbst.com/article40/dopdeo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、用戶體驗(yàn)、移動(dòng)網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)公司、定制網(wǎng)站、網(wǎng)站內(nèi)鏈
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容