Python-functools lru_cache mit Klassen-Methoden: Freigabe-Objekt
Wie kann ich functools' lru_cache im inneren Klassen ohne Speicherverlust?
Im folgenden minimalen Beispiel die foo
Instanz wird nicht freigegeben werden, obwohl aus Umfang und ohne referrer (andere als die lru_cache).
from functools import lru_cache
class BigClass:
pass
class Foo:
def __init__(self):
self.big = BigClass()
@lru_cache(maxsize=16)
def cached_method(self, x):
return x + 5
def fun():
foo = Foo()
print(foo.cached_method(10))
print(foo.cached_method(10)) # use cache
return 'something'
fun()
Aber foo
und damit foo.big
(a BigClass
) sind noch am Leben
import gc; gc.collect() # collect garbage
len([obj for obj in gc.get_objects() if isinstance(obj, Foo)]) # is 1
Das bedeutet, dass Foo/BigClass Instanzen sind immer noch wohnhaft in Speicher. Auch das löschen Foo
(del Foo
) wird Sie nicht loslassen wollen.
Warum ist lru_cache holding auf, um die Instanz überhaupt? Nicht die cache-Nutzung einige hash und nicht das eigentliche Objekt?
Was ist die empfohlene Weise verwenden lru_caches im inneren Klassen?
Kenne ich zwei workarounds:
Verwenden Sie pro Instanz caches oder den cache ignorieren-Objekt (was zu falschen Ergebnissen führen kann, obwohl)
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist nicht die sauberste Lösung, aber es ist völlig transparent für den Programmierer:
Er nimmt dieselben Parameter wie
lru_cache
, und funktioniert genauso. Aber es geht niemalsself
zulru_cache
und verwendet stattdessen eine pro-Instanzlru_cache
.lru_cache
'scache_clear
/cache_info
Funktionen (Umsetzung, die war, wo ich rempelte an Erster Stelle).__getitem__
. Irgendwelche Ideen, warum ? Es funktioniert, wenn Sie anrufeninstance.__getitem__(key)
aber nichtinstance[key]
.Stelle ich
methodtools
für diesen Anwendungsfall.pip install methodtools
zu installieren https://pypi.org/project/methodtools/Dann ist dein code funktioniert nur durch den Austausch functools zu methodtools.
Natürlich der gc testen, gibt auch 0 zu.
methodtools
wenn es bereitsring
?methodtools.lru_cache
verhält sich genau wiefunctools.lru_cache
durch die Wiederverwendungfunctools.lru_cache
im inneren, währendring.lru
schlägt vor, mehr features durch reimplementing lru Lagerung in python.methodtools.lru_cache
auf eine Methode verwendet eine getrennte Lagerung für jede Instanz der Klasse, während die Speicherung vonring.lru
teilen sich alle Instanzen der Klasse.