我想覆盖dict
,以便修改后的密钥会在修改后立即将dict
转储到pickle中。
为此,我重写了__setitem__
。以下代码:
__setitem__
以添加转储工作正常。但是,我需要考虑pickle.load()
在构建dict时也使用__setitem__
这一事实,并且不应该尝试将其转储到磁盘上(因为它实际上是从磁盘加载的) )。我使用的解决方案看起来很糟糕。
import pickle
import myconfig # en extension of logging to format logs across my scripts via myconfig.log
import sys
class CachedDict(dict):
def __init__(self, db="cache.pickle", **kwargs):
super().__init__()
self.db = db
try:
# load the axisting cache, if any
with open(self.db, 'rb') as f:
data = pickle.load(f)
self.update(data)
except FileNotFoundError:
# failed to load the cache, create a new one
myconfig.log.info("no cache {db} found, initializing".format(db=self.db))
with open(self.db, 'wb') as f:
pickle.dump(self, f)
else:
myconfig.log.info("loading from {db} cached dict {self}".format(self=self, db=self.db))
def __setitem__(self, key, value):
super().__setitem__(key, value)
# dump cache
myconfig.log.debug("updating dict {self} with {key}, {value}".format(self=self, key=key, value=value))
# do not write the cache when called from __init__: we are populating the dict
if sys._getframe(1).f_code.co_name != '__init__':
try:
with open(self.db, 'wb') as f:
pickle.dump(self, f)
except Exception as e:
myconfig.log.error("cannot update cache: {e}".format(e=e))
a = CachedDict("hello.pickle")
a['hello'] = 'world'
a[3] = 5
a['hello'] = 'wazaa'
myconfig.log.debug("final dict: {a}".format(a=a))
此输出
2016-01-11 12:59:54,134 | DEBUG | scratch_48 | 25 | __setitem__ | updating dict {3: 5} with 3, 5
2016-01-11 12:59:54,134 | DEBUG | scratch_48 | 25 | __setitem__ | updating dict {3: 5, 'hello': 'wazaa'} with hello, wazaa
2016-01-11 12:59:54,136 | INFO | scratch_48 | 20 | __init__ | loading from hello.pickle cached dict {3: 5, 'hello': 'wazaa'}
2016-01-11 12:59:54,136 | DEBUG | scratch_48 | 25 | __setitem__ | updating dict {3: 5, 'hello': 'world'} with hello, world
2016-01-11 12:59:54,137 | DEBUG | scratch_48 | 25 | __setitem__ | updating dict {3: 5, 'hello': 'world'} with 3, 5
2016-01-11 12:59:54,138 | DEBUG | scratch_48 | 25 | __setitem__ | updating dict {3: 5, 'hello': 'wazaa'} with hello, wazaa
2016-01-11 12:59:54,139 | DEBUG | scratch_48 | 39 | <module> | final dict: {3: 5, 'hello': 'wazaa'}
问题在于
行data = pickle.load(f)
有没有办法指示Python使用super()
版__setitem__
版本的单个案例?
答案 0 :(得分:0)
在更新dict并关闭文件后立即将数据写入文件, 如何阻止这个CachedDict可以用多个线程调用,或者可以在两次调用pickle.dump的时间间隔内由用户修改?
你能在CachedDict中包装一个普通的dict,然后在显式(或在_del __)中调用cachedDict.close时转储并关闭文件吗?
答案 1 :(得分:0)
怎么样,我认为代表团比继承更好
class CachedDict(): def __store(self): try: with open(self.db, 'wb') as f: pickle.dump(self.__dict, f) except Exception as e: print "cannot update cache: {e}".format(e=e) def __init__(self, db="cache.pickle", **kwargs): self.__dict = {} self.db = db try: # load the axisting cache, if any with open(self.db, 'rb') as f: data = pickle.load(f) self.update(data) except: self.__store() def __setitem__(self, key, value): self.__dict[key] = value self.__store() def __str__(self): return self.__dict.__str__()