專(zhuān)業(yè)建設(shè)網(wǎng)站企業(yè)wordpress swf
鶴壁市浩天電氣有限公司
2026/01/24 10:50:52
專(zhuān)業(yè)建設(shè)網(wǎng)站企業(yè),wordpress swf,優(yōu)秀品牌設(shè)計(jì)公司,信陽(yáng)網(wǎng)站建設(shè)培訓(xùn)Python數(shù)據(jù)持久化與序列化方法詳解在系統(tǒng)管理工作中#xff0c;構(gòu)建GUI應(yīng)用程序雖并非傳統(tǒng)職責(zé)#xff0c;但它是一項(xiàng)極具價(jià)值的技能。有時(shí)#xff0c;你可能需要為用戶(hù)創(chuàng)建簡(jiǎn)單應(yīng)用#xff1b;有時(shí)則是給自己用#xff1b;還有時(shí)#xff0c;雖非必需#xff0c;但它能讓…Python數(shù)據(jù)持久化與序列化方法詳解在系統(tǒng)管理工作中構(gòu)建GUI應(yīng)用程序雖并非傳統(tǒng)職責(zé)但它是一項(xiàng)極具價(jià)值的技能。有時(shí)你可能需要為用戶(hù)創(chuàng)建簡(jiǎn)單應(yīng)用有時(shí)則是給自己用還有時(shí)雖非必需但它能讓某些任務(wù)執(zhí)行得更順暢。當(dāng)你熟練掌握構(gòu)建GUI應(yīng)用的技巧后會(huì)驚訝地發(fā)現(xiàn)自己頻繁用到這項(xiàng)能力。而在數(shù)據(jù)處理方面數(shù)據(jù)持久化是一個(gè)重要概念。簡(jiǎn)單來(lái)說(shuō)數(shù)據(jù)持久化是指將數(shù)據(jù)保存起來(lái)以供后續(xù)使用即使保存數(shù)據(jù)的進(jìn)程終止數(shù)據(jù)依然存在。通常這是通過(guò)將數(shù)據(jù)轉(zhuǎn)換為某種格式并寫(xiě)入磁盤(pán)來(lái)實(shí)現(xiàn)的。數(shù)據(jù)格式有人類(lèi)可讀的如XML或YAML也有人類(lèi)無(wú)法直接使用的如Berkeley DB文件bdb或SQLite數(shù)據(jù)庫(kù)。1. 數(shù)據(jù)持久化的應(yīng)用場(chǎng)景以下是一些需要保存數(shù)據(jù)以供后續(xù)使用的場(chǎng)景-文件修改跟蹤腳本你有一個(gè)腳本用于跟蹤目錄中文件的最后修改日期需要偶爾運(yùn)行該腳本來(lái)查看自上次運(yùn)行后哪些文件發(fā)生了變化。此時(shí)文件的相關(guān)數(shù)據(jù)就需要保存下來(lái)下次運(yùn)行腳本時(shí)使用。-網(wǎng)絡(luò)性能監(jiān)測(cè)腳本有一臺(tái)機(jī)器存在潛在網(wǎng)絡(luò)問(wèn)題你決定每15分鐘運(yùn)行一次腳本查看它與網(wǎng)絡(luò)中其他多臺(tái)機(jī)器的ping響應(yīng)時(shí)間。這些ping時(shí)間數(shù)據(jù)可以保存到持久化數(shù)據(jù)文件中以便后續(xù)分析。2. 簡(jiǎn)單序列化方法序列化是將數(shù)據(jù)存儲(chǔ)到磁盤(pán)以供后續(xù)使用的過(guò)程這里先介紹簡(jiǎn)單序列化即保存數(shù)據(jù)到磁盤(pán)時(shí)不保存數(shù)據(jù)之間的關(guān)系。2.1 Pickle模塊Pickle是Python標(biāo)準(zhǔn)庫(kù)中的一個(gè)模塊是最基本的簡(jiǎn)單序列化機(jī)制。從農(nóng)業(yè)或烹飪的角度理解“pickling”就像是將食物保存起來(lái)放入罐中日后再使用。在Python中使用Pickle模塊可以將對(duì)象寫(xiě)入磁盤(pán)退出Python進(jìn)程之后再重新啟動(dòng)進(jìn)程從磁盤(pán)讀取對(duì)象并與之交互??蒔ickle的對(duì)象類(lèi)型- None、true和false- 整數(shù)、長(zhǎng)整數(shù)、浮點(diǎn)數(shù)、復(fù)數(shù)- 普通字符串和Unicode字符串- 僅包含可Pickle對(duì)象的元組、列表、集合和字典- 在模塊頂層定義的函數(shù)- 在模塊頂層定義的內(nèi)置函數(shù)- 在模塊頂層定義的類(lèi)- 其__dict__或__setstate__()可Pickle的此類(lèi)類(lèi)的實(shí)例序列化對(duì)象到磁盤(pán)In [1]: import pickle In [2]: some_dict {a: 1, b: 2} In [3]: pickle_file open(some_dict.pkl, w) In [4]: pickle.dump(some_dict, pickle_file) In [5]: pickle_file.close()反序列化Pickle文件In [1]: import pickle In [2]: pickle_file open(some_dict.pkl, r) In [3]: another_name_for_some_dict pickle.load(pickle_file) In [4]: another_name_for_some_dict Out[4]: {a: 1, b: 2}可以將多個(gè)對(duì)象存儲(chǔ)到一個(gè)Pickle文件中In [1]: list_of_dicts [{str(i): i} for i in range(5)] In [2]: list_of_dicts Out[2]: [{0: 0}, {1: 1}, {2: 2}, {3: 3}, {4: 4}] In [3]: import pickle In [4]: pickle_file open(list_of_dicts.pkl, w) In [5]: for d in list_of_dicts: ...: pickle.dump(d, pickle_file) ...: ...: In [6]: pickle_file.close()反序列化包含多個(gè)對(duì)象的Pickle文件In [1]: import pickle In [2]: pickle_file open(list_of_dicts.pkl, r) In [3]: while 1: ...: try: ...: print pickle.load(pickle_file) ...: except EOFError: ...: print EOF Error ...: break ...: ...: {0: 0} {1: 1} {2: 2} {3: 3} {4: 4} EOF ErrorPickle還可以處理自定義類(lèi)的對(duì)象。首先定義一個(gè)自定義類(lèi)#!/usr/bin/env python class MyClass(object): def __init__(self): self.data [] def __str__(self): return Custom Class MyClass Data:: %s % str(self.data) def add_item(self, item): self.data.append(item)將自定義類(lèi)的對(duì)象進(jìn)行Pickle序列化#!/usr/bin/env python import pickle import custom_class my_obj custom_class.MyClass() my_obj.add_item(1) my_obj.add_item(2) my_obj.add_item(3) pickle_file open(custom_class.pkl, w) pickle.dump(my_obj, pickle_file) pickle_file.close()反序列化自定義類(lèi)的Pickle文件#!/usr/bin/env python import pickle import custom_class pickle_file open(custom_class.pkl, r) my_obj pickle.load(pickle_file) print my_obj pickle_file.close()Pickle默認(rèn)使用一種接近人類(lèi)可讀的協(xié)議進(jìn)行序列化也可以選擇二進(jìn)制協(xié)議。二進(jìn)制協(xié)議在處理對(duì)象序列化時(shí)間較長(zhǎng)時(shí)可能更合適In [1]: import pickle In [2]: default_pickle_file open(default.pkl, w) In [3]: binary_pickle_file open(binary.pkl, wb) In [4]: d {a: 1} In [5]: pickle.dump(d, default_pickle_file) In [6]: pickle.dump(d, binary_pickle_file, -1) In [7]: default_pickle_file.close() In [8]: binary_pickle_file.close()2.2 cPickle模塊在Python標(biāo)準(zhǔn)庫(kù)中還有一個(gè)cPickle模塊它是用C語(yǔ)言實(shí)現(xiàn)的。如果發(fā)現(xiàn)對(duì)象的Pickle序列化過(guò)程耗時(shí)較長(zhǎng)可以考慮使用cPickle模塊其語(yǔ)法與pickle模塊相同。2.3 shelve模塊shelve模塊提供了一個(gè)簡(jiǎn)單易用的對(duì)象持久化接口簡(jiǎn)化了多個(gè)對(duì)象的持久化操作??梢詫⒍鄠€(gè)對(duì)象存儲(chǔ)在同一個(gè)持久化對(duì)象存儲(chǔ)中并輕松取回。使用shelve存儲(chǔ)對(duì)象類(lèi)似于使用Python字典。示例代碼In [1]: import shelve In [2]: d shelve.open(example.s) In [3]: d Out[3]: {} In [4]: d[key] some value In [5]: d.close() In [6]: d2 shelve.open(example.s) In [7]: d2 Out[7]: {key: some value}使用shelve時(shí)需要注意兩個(gè)問(wèn)題-關(guān)閉對(duì)象操作完成后必須調(diào)用close()方法否則對(duì)shelve對(duì)象所做的更改將不會(huì)被持久化。# 未關(guān)閉對(duì)象導(dǎo)致數(shù)據(jù)丟失示例 In [1]: import shelve In [2]: d shelve.open(lossy.s) In [3]: d[key] this is a key that will persist In [4]: d Out[4]: {key: this is a key that will persist} In [5]: d.close() # 再次打開(kāi)添加新項(xiàng)但不關(guān)閉 In [1]: import shelve In [2]: d shelve.open(lossy.s) In [3]: d Out[3]: {key: this is a key that will persist} In [4]: d[another_key] this is an entry that will not persist # 直接退出未調(diào)用d.close() # 再次打開(kāi)查看 In [1]: import shelve In [2]: d shelve.open(lossy.s) In [3]: d Out[3]: {key: this is a key that will persist}可變對(duì)象的修改默認(rèn)情況下對(duì)持久化對(duì)象的內(nèi)聯(lián)更改不會(huì)被捕獲??梢酝ㄟ^(guò)兩種方法解決特定針對(duì)性方法重新賦值給shelve對(duì)象。In [1]: import shelve In [2]: d shelve.open(mutable_nonlossy.s) In [3]: d[key] [] In [4]: temp_list d[key] In [5]: temp_list.append(1) In [6]: d[key] temp_list In [7]: d.close()通用的全面方法設(shè)置writeback標(biāo)志為T(mén)rue。但這樣會(huì)將訪(fǎng)問(wèn)的對(duì)象緩存到內(nèi)存中在調(diào)用close()時(shí)再進(jìn)行持久化可能會(huì)增加內(nèi)存使用和文件同步時(shí)間。In [1]: import shelve In [2]: d shelve.open(mutable_nonlossy.s, writebackTrue) In [3]: d[key] [] In [4]: d[key].append(1) In [5]: d.close()3. YAML模塊YAML全稱(chēng)可能是“YAML ain’t markup language”或“yet another markup language”是一種常用于以純文本布局存儲(chǔ)、檢索和更新數(shù)據(jù)的格式數(shù)據(jù)通常具有層次結(jié)構(gòu)。在Python中使用YAML可先通過(guò)easy_install PyYAML進(jìn)行安裝。選擇YAML而非內(nèi)置的pickle有兩個(gè)吸引人的原因-人類(lèi)可讀語(yǔ)法類(lèi)似于配置文件在編輯配置文件是個(gè)不錯(cuò)選擇的場(chǎng)景下YAML可能是個(gè)好的選擇。-多語(yǔ)言支持YAML解析器已在許多其他語(yǔ)言中實(shí)現(xiàn)如果你需要在Python應(yīng)用程序和其他語(yǔ)言編寫(xiě)的應(yīng)用程序之間傳輸數(shù)據(jù)YAML可以作為一個(gè)很好的中間解決方案。序列化示例In [1]: import yaml In [2]: yaml_file open(test.yaml, w) In [3]: d {foo: a, bar: b, bam: [1, 2,3]} In [4]: yaml.dump(d, yaml_file, default_flow_styleFalse) In [5]: yaml_file.close()生成的YAML文件內(nèi)容如下bam: - 1 - 2 - 3 bar: b foo: a反序列化示例In [1]: import yaml In [2]: yaml_file open(test.yaml, r) In [3]: yaml.load(yaml_file) Out[3]: {bam: [1, 2, 3], bar: b, foo: a}YAML還支持非塊模式的序列化In [1]: import yaml In [2]: yaml_file open(nonblock.yaml, w) In [3]: d {foo: a, bar: b, bam: [1, 2,3]} In [4]: yaml.dump(d, yaml_file) In [5]: yaml_file.close()生成的非塊模式Y(jié)AML文件內(nèi)容如下bam: [1, 2, 3] bar: b foo: aYAML在處理自定義類(lèi)時(shí)的行為與pickle類(lèi)似。以下是序列化和反序列化自定義類(lèi)對(duì)象的示例序列化自定義類(lèi)對(duì)象#!/usr/bin/env python import yaml import custom_class my_obj custom_class.MyClass() my_obj.add_item(1) my_obj.add_item(2) my_obj.add_item(3) yaml_file open(custom_class.yaml, w) yaml.dump(my_obj, yaml_file) yaml_file.close()反序列化自定義類(lèi)對(duì)象#!/usr/bin/env python import yaml import custom_class yaml_file open(custom_class.yaml, r) my_obj yaml.load(yaml_file) print my_obj yaml_file.close()總結(jié)本文詳細(xì)介紹了Python中數(shù)據(jù)持久化和簡(jiǎn)單序列化的多種方法包括pickle、cPickle、shelve和YAML。每種方法都有其特點(diǎn)和適用場(chǎng)景pickle是基本的序列化模塊cPickle性能更優(yōu)shelve簡(jiǎn)化了多對(duì)象持久化YAML具有人類(lèi)可讀和多語(yǔ)言支持的優(yōu)勢(shì)。在實(shí)際應(yīng)用中需要根據(jù)具體需求選擇合適的方法。以下是這些序列化方法的比較表格| 方法 | 特點(diǎn) | 適用場(chǎng)景 || ---- | ---- | ---- || pickle | 基本的序列化模塊支持自定義類(lèi)對(duì)象默認(rèn)協(xié)議接近人類(lèi)可讀 | 簡(jiǎn)單對(duì)象的序列化和反序列化對(duì)性能要求不高 || cPickle | 用C語(yǔ)言實(shí)現(xiàn)性能優(yōu)于pickle | 對(duì)象序列化耗時(shí)較長(zhǎng)的情況 || shelve | 提供簡(jiǎn)單易用的多對(duì)象持久化接口類(lèi)似字典操作 | 需要存儲(chǔ)多個(gè)對(duì)象并方便取回的場(chǎng)景 || YAML | 人類(lèi)可讀多語(yǔ)言支持?jǐn)?shù)據(jù)通常具有層次結(jié)構(gòu) | 需要在不同語(yǔ)言應(yīng)用程序間傳輸數(shù)據(jù)或數(shù)據(jù)需要人工編輯的場(chǎng)景 |通過(guò)合理運(yùn)用這些方法可以更好地實(shí)現(xiàn)數(shù)據(jù)的持久化存儲(chǔ)和管理。以下是使用pickle模塊進(jìn)行對(duì)象序列化和反序列化的流程圖graph LR classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px; classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px; classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px; A([開(kāi)始]):::startend -- B(導(dǎo)入pickle模塊):::process B -- C(創(chuàng)建要序列化的對(duì)象):::process C -- D(打開(kāi)文件以寫(xiě)入模式):::process D -- E(使用pickle.dump()序列化對(duì)象到文件):::process E -- F(關(guān)閉文件):::process F -- G{是否需要反序列化?}:::decision G --|是| H(打開(kāi)文件以讀取模式):::process H -- I(使用pickle.load()從文件中反序列化對(duì)象):::process I -- J(使用反序列化后的對(duì)象):::process J -- K([結(jié)束]):::startend G --|否| K([結(jié)束]):::startend這個(gè)流程圖展示了使用pickle模塊進(jìn)行對(duì)象序列化和反序列化的基本流程。首先導(dǎo)入pickle模塊創(chuàng)建要序列化的對(duì)象然后將對(duì)象寫(xiě)入文件。接著根據(jù)是否需要反序列化決定是否從文件中讀取對(duì)象。如果需要反序列化將讀取文件并使用反序列化后的對(duì)象如果不需要?jiǎng)t直接結(jié)束流程。這個(gè)流程清晰地展示了pickle模塊的使用步驟。Python數(shù)據(jù)持久化與序列化方法詳解在之前的內(nèi)容中我們已經(jīng)對(duì)Python數(shù)據(jù)持久化的多種簡(jiǎn)單序列化方法進(jìn)行了詳細(xì)介紹。接下來(lái)我們將進(jìn)一步探討這些方法在實(shí)際應(yīng)用中的注意事項(xiàng)和一些拓展內(nèi)容以及對(duì)不同序列化方法的性能對(duì)比分析。4. 序列化方法實(shí)際應(yīng)用注意事項(xiàng)4.1 Pickle模塊的安全性問(wèn)題雖然pickle模塊非常方便但在使用時(shí)需要注意安全性問(wèn)題。由于pickle可以反序列化任意對(duì)象當(dāng)從不可信的源接收pickle數(shù)據(jù)時(shí)可能會(huì)執(zhí)行惡意代碼。例如如果一個(gè)攻擊者能夠控制pickle文件的內(nèi)容他們可以構(gòu)造一個(gè)惡意對(duì)象在反序列化時(shí)執(zhí)行任意代碼。因此在實(shí)際應(yīng)用中不要從不可信的源加載pickle數(shù)據(jù)。4.2 shelve模塊的文件鎖定問(wèn)題shelve模塊在多進(jìn)程或多線(xiàn)程環(huán)境下使用時(shí)可能會(huì)出現(xiàn)文件鎖定問(wèn)題。當(dāng)多個(gè)進(jìn)程或線(xiàn)程同時(shí)嘗試訪(fǎng)問(wèn)和修改同一個(gè)shelve文件時(shí)可能會(huì)導(dǎo)致數(shù)據(jù)不一致或文件損壞。為了避免這個(gè)問(wèn)題可以使用鎖機(jī)制來(lái)確保同一時(shí)間只有一個(gè)進(jìn)程或線(xiàn)程可以訪(fǎng)問(wèn)shelve文件。import shelve import threading # 創(chuàng)建一個(gè)鎖對(duì)象 lock threading.Lock() def update_shelve(): with lock: d shelve.open(example.s) try: if counter not in d: d[counter] 0 d[counter] 1 finally: d.close() # 創(chuàng)建多個(gè)線(xiàn)程來(lái)更新shelve文件 threads [] for _ in range(10): t threading.Thread(targetupdate_shelve) threads.append(t) t.start() # 等待所有線(xiàn)程完成 for t in threads: t.join() # 查看最終結(jié)果 d shelve.open(example.s) print(d[counter]) d.close()4.3 YAML模塊的性能問(wèn)題雖然YAML具有人類(lèi)可讀和多語(yǔ)言支持的優(yōu)點(diǎn)但在處理大量數(shù)據(jù)或?qū)π阅芤筝^高的場(chǎng)景下YAML的序列化和反序列化速度可能較慢。這是因?yàn)閅AML需要解析和生成文本格式的數(shù)據(jù)相比二進(jìn)制格式的序列化方法性能會(huì)有所損失。在這種情況下可以考慮使用其他性能更高的序列化方法如cPickle。5. 序列化方法性能對(duì)比分析為了更直觀地了解不同序列化方法的性能差異我們可以進(jìn)行一個(gè)簡(jiǎn)單的性能測(cè)試。以下是一個(gè)測(cè)試代碼示例用于比較pickle、cPickle和YAML在序列化和反序列化一個(gè)大型字典時(shí)的性能。import pickle import cPickle import yaml import time # 創(chuàng)建一個(gè)大型字典 large_dict {str(i): i for i in range(10000)} # 測(cè)試pickle的性能 start_time time.time() pickle_file open(pickle_test.pkl, w) pickle.dump(large_dict, pickle_file) pickle_file.close() pickle_file open(pickle_test.pkl, r) loaded_dict_pickle pickle.load(pickle_file) pickle_file.close() pickle_time time.time() - start_time # 測(cè)試cPickle的性能 start_time time.time() cPickle_file open(cPickle_test.pkl, wb) cPickle.dump(large_dict, cPickle_file) cPickle_file.close() cPickle_file open(cPickle_test.pkl, rb) loaded_dict_cPickle cPickle.load(cPickle_file) cPickle_file.close() cPickle_time time.time() - start_time # 測(cè)試YAML的性能 start_time time.time() yaml_file open(yaml_test.yaml, w) yaml.dump(large_dict, yaml_file) yaml_file.close() yaml_file open(yaml_test.yaml, r) loaded_dict_yaml yaml.load(yaml_file) yaml_file.close() yaml_time time.time() - start_time # 輸出性能測(cè)試結(jié)果 print(fPickle序列化和反序列化時(shí)間: {pickle_time} 秒) print(fcPickle序列化和反序列化時(shí)間: {cPickle_time} 秒) print(fYAML序列化和反序列化時(shí)間: {yaml_time} 秒)以下是根據(jù)上述測(cè)試代碼可能得到的性能對(duì)比表格| 方法 | 序列化和反序列化時(shí)間秒 || ---- | ---- || pickle | 0.123 || cPickle | 0.034 || YAML | 0.567 |從表格中可以看出cPickle的性能明顯優(yōu)于pickle和YAML。這是因?yàn)閏Pickle是用C語(yǔ)言實(shí)現(xiàn)的執(zhí)行速度更快。而YAML由于需要處理文本格式的數(shù)據(jù)性能相對(duì)較差。6. 序列化方法的選擇建議根據(jù)不同的應(yīng)用場(chǎng)景和需求可以按照以下建議選擇合適的序列化方法-簡(jiǎn)單對(duì)象且對(duì)性能要求不高可以使用pickle模塊它是Python標(biāo)準(zhǔn)庫(kù)中的基本序列化方法支持自定義類(lèi)對(duì)象使用方便。-對(duì)性能要求較高優(yōu)先選擇cPickle模塊它的性能明顯優(yōu)于pickle尤其在處理大量數(shù)據(jù)時(shí)更加顯著。-需要存儲(chǔ)多個(gè)對(duì)象并方便取回使用shelve模塊它提供了類(lèi)似字典的操作接口簡(jiǎn)化了多對(duì)象的持久化操作。-需要在不同語(yǔ)言應(yīng)用程序間傳輸數(shù)據(jù)或數(shù)據(jù)需要人工編輯選擇YAML模塊它具有人類(lèi)可讀和多語(yǔ)言支持的優(yōu)點(diǎn)??偨Y(jié)本文全面介紹了Python中數(shù)據(jù)持久化和簡(jiǎn)單序列化的多種方法包括pickle、cPickle、shelve和YAML。詳細(xì)闡述了它們的使用方法、特點(diǎn)、適用場(chǎng)景以及在實(shí)際應(yīng)用中需要注意的問(wèn)題。通過(guò)性能對(duì)比分析我們可以更清楚地了解不同方法的性能差異從而在實(shí)際開(kāi)發(fā)中根據(jù)具體需求選擇最合適的序列化方法。以下是不同序列化方法選擇的決策流程圖graph LR classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px; classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px; classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px; A([開(kāi)始]):::startend -- B{是否需要多語(yǔ)言支持?}:::decision B --|是| C(YAML):::process B --|否| D{是否對(duì)性能要求高?}:::decision D --|是| E(cPickle):::process D --|否| F{是否需要存儲(chǔ)多個(gè)對(duì)象?}:::decision F --|是| G(shelve):::process F --|否| H(pickle):::process C -- I([結(jié)束]):::startend E -- I([結(jié)束]):::startend G -- I([結(jié)束]):::startend H -- I([結(jié)束]):::startend這個(gè)流程圖可以幫助我們?cè)诿鎸?duì)不同的需求時(shí)快速選擇合適的序列化方法。通過(guò)合理運(yùn)用這些序列化方法我們可以更好地實(shí)現(xiàn)數(shù)據(jù)的持久化存儲(chǔ)和管理提高程序的性能和可維護(hù)性。