Skip to content

Instantly share code, notes, and snippets.

@lucidfrontier45
Created March 11, 2016 01:46
Show Gist options
  • Select an option

  • Save lucidfrontier45/cb72db855a7193322e39 to your computer and use it in GitHub Desktop.

Select an option

Save lucidfrontier45/cb72db855a7193322e39 to your computer and use it in GitHub Desktop.
Python Dict with expiry
import time
from collections import UserDict
from threading import Lock, Event, Thread
from functional import seq
# <http://stackoverflow.com/questions/22498038/improve-current-implementation-of-a-setinterval-python/22498708#22498708>
def set_interval(interval, func, *args):
stopped = Event()
def loop():
while not stopped.wait(interval): # the first call is in `interval` secs
func(*args)
Thread(target=loop).start()
return stopped.set
class TimeoutableDict(UserDict):
def __init__(self, initialdata=None, lifetime=300):
self._lifetime = lifetime
self._lock = Lock()
self._timestamps = dict()
UserDict.__init__(self, initialdata)
self._cancel = set_interval(lifetime, self.clear_expired_items)
def __del__(self):
self._cancel()
def __setitem__(self, key, value):
now = time.time()
with self._lock:
self._timestamps[key] = now
self.data[key] = value
def __getitem__(self, key):
now = time.time()
with self._lock:
if key in self.data:
self._timestamps[key] = now
return self.data[key]
else:
return None
def __delitem__(self, key):
with self._lock:
if key in self.data:
self._timestamps.__delitem__(key)
self.data.__delitem__(key)
def clear_expired_items(self):
now = time.time()
def _clean_item(key):
self._timestamps.__delitem__(key)
self.data.__delitem__(key)
with self._lock:
keys_to_remove = seq(self.data.keys()) \
.filter(lambda k: now - self._timestamps[k] > self._lifetime) \
.to_list()
seq(keys_to_remove).for_each(_clean_item)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment