簡體   English   中英

使用Python永久存儲字典的優雅方式?

[英]Elegant way to store dictionary permanently with Python?

目前昂貴地解析文件,該文件生成約400個鍵值對的字典,其很少更新。 之前有一個解析文件的函數,用字典語法將其寫入文本文件(即dict = {'Adam': 'Room 430', 'Bob': 'Room 404'} )等,並復制並粘貼它到另一個函數,其唯一目的是返回解析的字典。

因此,在我將使用該字典的每個文件中,我將導入該函數,並將其分配給變量,現在是該字典。 想知道是否有更優雅的方法來做到這一點,這不涉及明確地復制和粘貼代碼? 使用數據庫似乎是不必要的,並且文本文件給了我在將其添加到函數之前查看解析是否正確完成的好處。 但我願意接受建議。

為什么不將它轉儲到JSON文件,然后從你需要的地方加載它?

import json

with open('my_dict.json', 'w') as f:
    json.dump(my_dict, f)

# elsewhere...

with open('my_dict.json') as f:
    my_dict = json.load(f)

從JSON加載相當有效。

另一個選擇是使用pickle ,但與JSON不同,它生成的文件不是人類可讀的,所以你會丟失你喜歡的舊方法的視覺驗證。

為什么搞亂所有這些序列化方法? 它已經作為Python dict寫入文件(雖然名字'dict'不幸)。 更改程序以使用更好的變量名稱寫出數據 - 可能是“數據”或“目錄”,並將文件保存為Python文件,例如data.py. 然后,您可以直接在運行時導入數據,而無需任何笨拙的復制/粘貼或JSON /擱置/等。 解析:

from data import catalog

在許多情況下,JSON可能是正確的方法; 但可能有另一種選擇。 它看起來像你的鍵和你的值總是字符串,是嗎? 您可以考慮使用dbm / anydbm 這些是“數據庫”,但它們的行為幾乎與字典完全相同。 它們非常適合廉價的數據持久性。

>>> import anydbm
>>> dict_of_strings = anydbm.open('data', 'c')
>>> dict_of_strings['foo'] = 'bar'
>>> dict_of_strings.close()
>>> dict_of_strings = anydbm.open('data')
>>> dict_of_strings['foo']
'bar'

如果鍵都是字符串,則可以使用擱置模塊

架子是一個持久的,類似字典的對象。 與“dbm”數據庫的區別在於,架子中的值(而不是鍵!)可以是基本上任意的Python對象 - pickle模塊可以處理的任何東西。 這包括大多數類實例,遞歸數據類型和包含許多共享子對象的對象。 鍵是普通的字符串。

如果您需要使用其他語言的數據, json將是一個不錯的選擇

如果存儲效率很重要,請使用Pickle或CPickle(用於執行性能增益)。 正如Amber指出的那樣,你也可以通過Json轉儲/加載。 它將是人類可讀的,但需要更多的磁盤。

我建議您考慮使用shelve模塊,因為您的數據結構是映射。 這是我對類似問題的回答如果我想構建一個自定義數據庫,我怎么辦? 我的另一個答案中還有一些示例代碼,用於推廣其用於如何獲取對象數據庫的問題?

ActiveState具有高度評級的PersistentDict配方,它支持csv,json和pickle輸出文件格式。 它非常快,因為所有這三種格式都是用C實現的(雖然配方本身就是純Python),所以它在打開時將整個文件讀入內存的事實可能是可以接受的。

在JSON方向上還有一些叫做simpleJSON的東西。 我第一次在python中使用json json庫對我來說沒有用/我無法弄明白。 simpleJSON更容易使用

JSON(或YAML,或其他)序列化可能更好,但如果您已經使用python語法將字典編寫為文本文件,並使用變量名稱綁定,則可以將其寫入.py文件。 然后該python文件將是可導入的並且可以按原樣使用。 不需要“返回字典的函數”方法,因為您可以直接將其用作該文件中的全局。 例如

# generated.py
please_dont_use_dict_as_a_variable_name = {'Adam': 'Room 430', 'Bob': 'Room 404'}

而不是:

# manually_copied.py
def get_dict():
    return {'Adam': 'Room 430', 'Bob': 'Room 404'}

唯一的區別是, manually_copied.get_dict給你每次詞典的最新副本,而generated.please_dont_use_dict_as_a_variable_name [1]是一個單一的共享對象。 如果您在檢索程序后修改程序中的字典,這可能很重要,但如果您需要獨立修改其他副本,則可以始終使用copy.copycopy.deepcopy創建新副本。


[1] dictliststrintmap等通常被視為錯誤的變量名。 原因是它們已經被定義為內置函數,並且非常常用。 因此,如果你給出類似名稱的東西,至少它會導致閱讀你的代碼的人(包括你離開一段時間后)的認知不協調,因為他們必須記住“ dict doesn”這意味着它通常在這里做什么“。 也很可能在某些時候你會得到一個真實的解決bug報告dict對象不可調用(或者其他東西),因為某些代碼試圖使用類型 dict ,但是得到了字典你綁定到名字dict對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM