2014-05-20 17 views
2

我保持一個字典,正在通過用戶界面進行修改。代替具有用戶控制的「保存」功能,我希望字典在其更改時寫入JSON文件。我知道保存的機制,但不知道如何觸發字典中更改的保存。這是可能的,如果是的話,如何?保存字典,當它改變

+0

FYI這正是'shelve'呢,雖然不是以JSON格式。 – roippi

+0

@roippi:和'shelve'也使用'collections.MutableMapping'。 –

回答

4

您不能使用默認的dict類型,但可以使用自定義字典子類或collections.MutableMapping abstract base class的子類以及攔截方法來修改字典,以便觸發保存。

對後者最簡單;它將所有修改方法映射到__setitem__。您需要提供overview table抽象方法列中的所有方法。

這裏是我的這樣一類的速寫:

import json 
from collections import MutableMapping 

class JSONBackedMapping(MutableMapping): 
    def __init__(self, filename, initial=None, **kw): 
     self._filename = filename 
     try: 
      # Try and load the file 
      self.load() 
     except (ValueError, IOError): 
      # failure, fall back to the initial object 
      self._data = initial or {} 
     self._data.update(**kw) 

    def load(self): 
     with open(self._filename, 'r') as inf: 
      self._data = json.load(inf) 

    def save(self): 
     with open(self._filename, 'w') as outf: 
      json.dump(self._data, outf) 

    def __repr__(self): 
     return '<{}({!r}, {})>'.format(
      type(self).__name__, 
      self._filename, self._data) 

    def __len__(self):   return len(self._data) 
    def __iter__(self):   return iter(self._data) 
    def __getitem__(self, item): return self._data[item] 

    def __delitem__(self, item): 
     del self._data[item] 
     self.save() 

    def __setitem__(self, item, value): 
     self._data[item] = value 
     self.save() 

這會從所給的文件加載,或者如果失敗與初始字典開始。您可以添加其他鍵值對作爲關鍵字參數。它所做的任何更改將被自動保存爲JSON給定文件名:

>>> data = JSONBackedMapping('data.json') 
>>> data 
<JSONBackedMapping('data.json', {})> 
>>> data['foo'] = 'bar' 
>>> data['spam'] = ['eggs', 'ham'] 
>>> print open('data.json').read() 
{"foo": "bar", "spam": ["eggs", "ham"]} 
>>> del data 
>>> data = JSONBackedMapping('data.json') 
>>> data 
<JSONBackedMapping('data.json', {u'foo': u'bar', u'spam': [u'eggs', u'ham']})>