2012-08-06 21 views
14

目前代價很高的解析文件,該文件會生成大約400個密鑰值對的字典,這些字符很少更新。以前有一個解析文件的函數,用字典語法(例如dict = {'Adam': 'Room 430', 'Bob': 'Room 404'})等將其寫入文本文件,並將其複製並粘貼到另一個函數中,該函數的唯一目的是返回解析的字典。用Python永久存儲字典的優雅方式?

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

+0

可能重複:http://stackoverflow.com/questions/7100125/storing-python-dictionaries – 2012-08-06 00:31:30

+0

序列化到JSON,JSON寫一個文件,讀取文件,'json.loads()'之後? – favoretti 2012-08-06 00:32:21

+0

另請參閱:[如何將字典保存到Python中的文件?](http://stackoverflow.com/q/19201290/562769)和[存儲Python字典](http://stackoverflow.com/q/7100125/562769)。 – 2016-04-29 08:56:12

回答

33

爲什麼不把它轉儲到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不同的是,它生成的文件不具有人類可讀性,因此您從舊方法中忽略了您喜歡的可視化驗證。

3

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

4

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' 
4

如果密鑰都是字符串,則可以使用shelve模塊

一個shelf是一個持久的,類似字典的對象。與 「dbm」數據庫的不同之處在於,貨架上的值(不是密鑰!)可以是基本上任意的Python對象 - 任何可以由pickle模塊 處理的東西。這包括大多數類實例,遞歸數據類型, 和包含大量共享子對象的對象。密鑰是 普通字符串。

json將是一個不錯的選擇,如果你需要從其他語言

+0

我也讀過一些讓我相信'shelve'文件不是跨平臺兼容的東西,因爲所使用的底層數據庫可能會有所不同(並且沒有一個好的方法來控制它)。 – martineau 2012-11-10 18:40:51

2

我建議你考慮使用shelve模塊,因爲你的數據結構是一個映射,使用的數據。 那是我answer標題爲If I want to build a custom database, how could I?還有一點示例代碼在我的另一個answer促進其使用的問題類似的問題How to get a object database?

ActiveState公司有着很高的評價PersistentDict配方支持CSV,JSON和鹹菜輸出文件格式。它的速度相當快,因爲​​所有這三種格式都是在C中實現的(儘管配方本身是純Python),所以它在打開時將整個文件讀入內存的事實可能是可以接受的。

0

在JSON方向上還有一些名爲simpleJSON的東西。我第一次在python中使用json json庫不適合我/我無法弄清楚。 simpleJSON更容易使用

0

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'這意味着它通常在這裏做什麼「。在某些時候,你很可能會得到一個令人生氣的解決方案,因爲某些代碼試圖使用類型dict而不是可調用對象(或某物)而不是名稱爲dict的字典對象。

14

爲什麼混淆所有這些序列化方法?它已經以Python代碼的形式寫入文件(儘管使用了不幸的名字'dict')。改變你的程序寫出更好的變量名稱 - 也許是'數據'或'目錄',並將文件保存爲Python文件,比如data.py。然後,您可以直接在運行時導入數據,而無需任何笨拙的複製/粘貼或JSON /擱置等。解析:

from data import catalog 
+1

+1:這是OP的問題的最佳答案,恕我直言。 – martineau 2012-11-10 19:01:45