Ich bin nach einem threadsicheren Python-Container, wo die Werte nach einiger Zeit automatisch entfernt werden. Existiert eine solche Klasse?Container, wo Werte in Python ablaufen
Antwort
Hier ist ein Thread sichere Version von ExpireCounter:
import datetime
import collections
import threading
class ExpireCounter:
"""Tracks how many events were added in the preceding time period
"""
def __init__(self, timeout=1):
self.lock=threading.Lock()
self.timeout = timeout
self.events = collections.deque()
def add(self,item):
"""Add event time
"""
with self.lock:
self.events.append(item)
threading.Timer(self.timeout,self.expire).start()
def __len__(self):
"""Return number of active events
"""
with self.lock:
return len(self.events)
def expire(self):
"""Remove any expired events
"""
with self.lock:
self.events.popleft()
def __str__(self):
with self.lock:
return str(self.events)
, die wie folgt verwendet werden kann:
import time
c = ExpireCounter()
assert(len(c) == 0)
print(c)
# deque([])
c.add(datetime.datetime.now())
time.sleep(0.75)
c.add(datetime.datetime.now())
assert(len(c) == 2)
print(c)
# deque([datetime.datetime(2010, 11, 19, 8, 50, 0, 91426), datetime.datetime(2010, 11, 19, 8, 50, 0, 842715)])
time.sleep(0.75)
assert(len(c) == 1)
print(c)
# deque([datetime.datetime(2010, 11, 19, 8, 50, 0, 842715)])
danke! Ich mag die Thread-Zeitüberschreitung. War mein Beispiel nicht threadsicher? Die Dokumentation sagt "Deque ist eine alternative Implementierung von unbegrenzten Warteschlangen mit schnellen atomaren append() - und popleft() -Operationen, die nicht gesperrt werden müssen." – hoju
@Plumo: Ich bin kein Experte in der Beurteilung der Thread-Sicherheit, aber ich denke, Ihre Version von ExpireCounter ist möglicherweise nicht Thread-sicher. In der 'add'-Methode kann auf den Aufruf von' datetime.now() 'nicht sofort der Aufruf von' self.events.append' folgen. Stellen Sie sich mehrere Threads vor, die die add-Methode fast gleichzeitig aufrufen. Viele Aufrufe von "datetime.now", aber die Ergebnisse werden an "self.events" in einer uneinheitlichen Reihenfolge angehängt. Wenn 'self.events' nicht chronologisch geordnet ist, endet die while-Schleife in der' expire'-Methode möglicherweise zu früh. Daher kann es passieren, dass alle Elemente, die das Zeitlimit überschritten haben, nicht "verloren" werden. – unutbu
Vielleicht möchten Sie einen LRU-Cache. Hier ist ein Ich habe Sinn versuchen:
http://pypi.python.org/pypi/repoze.lru
Es Thread-sicher zu sein scheint.
nein nicht LRU. Ich möchte, dass ein Wert nach genau dem angegebenen Timeout abläuft, unabhängig davon, wie viele Werte ich habe und ob ich darauf zugreife. – hoju
In diesem Fall könnten Sie mit jedem Wert eine Ablaufzeit speichern. Welche Art von Containersemantik möchten Sie verwenden: Liste, Satz, Diktat oder etwas anderes? –
nicht mit Art des Behälters betroffen, solange es Thread-sicher ist – hoju
Dies ist mehr oder weniger das, was ich jetzt will:
from datetime import datetime, timedelta
from collections import deque
class ExpireCounter:
"""Tracks how many events were added in the preceding time period
"""
def __init__(self, timeout=timedelta(seconds=1)):
self.timeout = timeout
self.events = deque()
def add(self):
"""Add event time
"""
self.events.append(datetime.now())
def __len__(self):
"""Return number of active events
"""
self.expire()
return len(self.events)
def expire(self):
"""Remove any expired events
"""
now = datetime.now()
try:
while self.events[0] + self.timeout < now:
self.events.popleft()
except IndexError:
pass # no more events
if __name__ == '__main__':
import time
c = ExpireCounter()
assert(len(c) == 0)
c.inc()
time.sleep(0.75)
c.inc()
assert(len(c) == 2)
time.sleep(0.75)
assert(len(c) == 1)
möglich duplizieren: http://stackoverflow.com/questions/3927166/automatisch-expiring-variable – mouad
Ich bin nach einem Thread s eine Klasse mit Timeouts für jeden Wert. In diesem Beispiel wird eine Liste und ein globales Timeout verwendet. – hoju