是否可以使用super()方法,否则隐式使用?

时间:2016-01-11 12:07:50

标签: python class

我想覆盖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__版本的单个案例?

2 个答案:

答案 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__()