Heim >Backend-Entwicklung >Python-Tutorial >Python-Caching veränderlicher Werte

Python-Caching veränderlicher Werte

Barbara Streisand
Barbara StreisandOriginal
2025-01-26 16:13:10898Durchsuche

Python Caching mutable values

Caching beschleunigt die Verarbeitung erheblich, von Vorgängen auf CPU-Ebene bis hin zu Datenbankschnittstellen. Die Cache-Invalidierung – also die Bestimmung, wann zwischengespeicherte Daten entfernt werden müssen – ist eine komplexe Herausforderung. Dieser Beitrag befasst sich mit einem einfacheren, aber heimtückischen Caching-Problem.

Dieses Problem, das 18 Monate lang lauerte, trat erst auf, als Benutzer vom empfohlenen Nutzungsmuster abwichen. Das Problem entstand durch ein benutzerdefiniertes Framework für maschinelles Lernen (ML) (basierend auf scikit-learn) in meiner Organisation. Dieses Framework greift häufig auf mehrere Datenquellen zu und erfordert eine Caching-Ebene zur Leistungs- und Kostenoptimierung (Reduzierung der BigQuery-Ausgangskosten).

Anfänglich wurde lru_cache verwendet, aber für statische Daten, auf die während der Entwicklung häufig zugegriffen wird, war ein persistenter Cache erforderlich. DiskCache, eine Python-Bibliothek mit SQLite, wurde aufgrund ihrer Einfachheit und Kompatibilität mit unserer 32-Prozess-Umgebung und Pandas DataFrames (bis zu 500 MB) ausgewählt. Darüber wurde eine lru_cache-Ebene für den In-Memory-Zugriff hinzugefügt.

Das Problem trat auf, als mehr Benutzer mit dem Framework experimentierten. Es wurden zufällig falsche Ergebnisse gemeldet, die sich nur schwer konsistent reproduzieren ließen. Die Hauptursache: direkte Änderung der zwischengespeicherten Pandas DataFrames.

Unser Codierungsstandard erforderte die Erstellung neuer DataFrames nach jeder Verarbeitung. Einige Benutzer verwendeten jedoch aus Gewohnheit inplace=True und änderten das zwischengespeicherte Objekt direkt. Dadurch wurden nicht nur die unmittelbaren Ergebnisse verändert, sondern auch die zwischengespeicherten Daten beschädigt, was sich auf nachfolgende Anfragen auswirkte.

Betrachten Sie zur Veranschaulichung dieses vereinfachte Beispiel mit Wörterbüchern:

<code class="language-python">from functools import lru_cache
import time
import typing as t
from copy import deepcopy

@lru_cache
def expensive_func(keys: str, vals: t.Any) -> dict:
    time.sleep(3)
    return dict(zip(keys, vals))


def main():
    e1 = expensive_func(('a', 'b', 'c'), (1, 2, 3))
    print(e1)

    e2 = expensive_func(('a', 'b', 'c'), (1, 2, 3))
    print(e2)

    e2['d'] = "amazing"

    print(e2)

    e3 = expensive_func(('a', 'b', 'c'), (1, 2, 3))
    print(e3)


if __name__ == "__main__":
    main()</code>

lru_cache stellt eine Referenz dar, keine Kopie. Durch Ändern von e2 werden die zwischengespeicherten Daten geändert.

Lösung:

Die Lösung besteht darin, eine tiefe Kopie des zwischengespeicherten Objekts zurückzugeben:

<code class="language-python">from functools import lru_cache, wraps
from copy import deepcopy

def custom_cache(func):
    cached_func = lru_cache(func)

    @wraps(func)
    def _wrapper(*args, **kwargs):
        return deepcopy(cached_func(*args, **kwargs))

    return _wrapper</code>

Dies führt zu einem geringen Mehraufwand (Datenduplizierung), verhindert jedoch eine Datenbeschädigung.

Wichtige Erkenntnisse:

  • Ein tieferes Verständnis des Referenzverhaltens von lru_cache.
  • Die Einhaltung von Codierungsstandards minimiert Fehler.
  • Berücksichtigen Sie Benutzerabweichungen von Best Practices bei der Implementierung. Robustheit geht oft vor Eleganz.

Das obige ist der detaillierte Inhalt vonPython-Caching veränderlicher Werte. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn