10
votes

Python: Construire un cache LRU

J'ai autour 6,00 000 entrées dans mongodub dans le format suivant: xxx

  • fonction pourrait être n'importe quel mot,
  • catégorie est positif ou négatif, et
  • comptage indique combien de fois une fonctionnalité survenue dans un document pour cette catégorie.

    Je veux mettre en cache le top 1000 tuples, disons de manière à ne pas interroger la base de données à chaque fois.

    Comment construire un cache LRU dans Python? Ou y a-t-il des solutions connues à cela?


0 commentaires

4 Réponses :


3
votes

Python 3.2 FuncTools comprend un Cache LRU . Vous pouvez facilement cerourir de Repo , vérifier si vous Doit-le ajuster pour travailler avec Python 2 (ne devrait pas être trop difficile - peut-être utiliser iTertools au lieu de certaines cométiches - Demandez si vous avez besoin d'aide) et être fait. Vous devez envelopper la question dans un appelable et vous assurer que cela dépend des arguments de la fonction (hachable), cependant.


5 commentaires

Cela semble intéressant, mais comment je l'obtiens de repo ??? Je ne sais pas comment faire ça \


@learner: La voie la plus simple serait la plus simple du fichier que j'ai lié à.


J'ai essayé mais quand j'essaie d'importer des fonctions de fonctionnement, il jette une erreur >>> Importer FuncTools Traceback (dernier appel en dernier): fichier "", ligne 1, dans fichier "FuncTools.py", ligne 151 hits non localisés , Misses ^ SyntaxError: erreur de syntaxe invalide dans SYS.EXCEPTHOOK:


@learner: Ah, bien sûr. NonLocal est un nouveau mot-clé Python 3 pour prendre en charge la fermeture. Cela peut être imité avec un hack sale, mais travaillant et succinct. Je pense que je résout ce problème, mais un nouveau est apparu: il utilise Collections.OrderedDict , qui est uniquement inclus dans 2.7+. En outre, le code semble être cassé O.O (faire référence à ordonnéddic.move_to_end qui n'existe pas) ...


Une implémentation de commande ordonnée est disponible formulaire PYPI.PHYTHON.ORG/PYPI/OREDEREDDICT . Cache.MOVE_TO_END (touche) est facilement implémenté comme Cache [clé] = cache.pop (clé) . Le sale baccalauréat est d'initialiser hits et manque comme hits_misses = [0, 0] et remplacer hits avec hits_misses [0] et manque avec hits_misses [1] .



6
votes

Outre la version incluse dans Python 3.2, il existe des recettes de cache LRU dans le Python Cookbook y compris ces par Python Core Developer Raymond Hettinger.


0 commentaires

20
votes

le Cache LRU dans Python3.3 a o (1) Insertion, suppression et recherche.

La conception utilise une liste d'entrées circulaire doublement liée (arrangée la plus ancienne au moins) et une table de hachage pour localiser des liens individuels. Les hits de cache utilisent la table de hachage pour trouver le lien correspondant et le déplacer à la tête de la liste. Cache Misses Supprimer la liaison la plus ancienne et créez un nouveau lien à la tête de la liste liée. P>

Voici une version simplifiée (mais rapide) dans 33 lignes de Python très basique (utilisant uniquement des opérations de dictionnaire simple et de liste) . Il fonctionne sur python2.0 et plus tard (ou pypy ou jython ou python3.x): p> xxx pré>

à partir de Python 3.1, CommandéDict Le rend encore plus simple d'implémenter un cache LRU: P>

from collections import OrderedDict

class LRU_Cache:

    def __init__(self, original_function, maxsize=1024):
        self.original_function = original_function
        self.maxsize = maxsize
        self.mapping = OrderedDict()

    def __call__(self, *key):
        mapping = self.mapping
        try:
            value = mapping[key]
            mapping.move_to_end(key)
        except KeyError:
            value = self.original_function(*key)
            if len(mapping) >= self.maxsize:
                mapping.popitem(False)
            mapping[key] = value
        return value


0 commentaires

1
votes

Il y a aussi des backports de la version Python 3.3 de Lru_cache, telle que cette qui fonctionne sur python 2.7. Si vous êtes intéressé par deux couches de mise en cache (sinon mis en cache dans l'instance, il vérifiera un cache partagé) J'ai créé lru2cache Basé sur le Backport de Lru_Cache.


0 commentaires