Не удается получить кэш мензурки - PullRequest
1 голос
/ 03 июля 2010

Я пытаюсь использовать библиотеку кэширования Beaker, но не могу заставить ее работать.

Вот мой тестовый код.

class IndexHandler():
    @cache.cache('search_func', expire=300)
    def get_results(self, query):
        results = get_results(query)
        return results

    def get(self, query):
        results = self.get_results(query)
        return render_index(results=results)

Я пробовал примеры в документации Beaker, но все, что я вижу, это

<type 'exceptions.TypeError'> at /
can't pickle generator objects

Я явно что-то упустил, но не смог найти решение.

Кстати, эта проблема возникает, если для типа кэша установлено значение "file".

Ответы [ 3 ]

3 голосов
/ 02 января 2011

Если вы сконфигурируете beaker для сохранения в файловой системе, вы можете легко увидеть, что каждый аргумент также выбирается. Пример:

tp3
sS'tags <myapp.controllers.tags.TagsController object at 0x103363c10> <MySQLdb.cursors.Cursor object at 0x103363dd0> apple'
p4

Обратите внимание, что «ключ» кэша содержит не только мое ключевое слово «яблоко», но и информацию, специфичную для экземпляра. Это довольно плохо, потому что особенно «я» не будет одинаковым при всех вызовах. Кэш будет каждый раз пропускать (и заполняться бесполезными ключами.)

Метод с аннотацией кеша должен только иметь аргументы, соответствующие любому «ключу», который вы имеете в виду. Перефразируя это, предположим, что вы хотите сохранить тот факт, что «Джон» соответствует значению 555-1212, и вы хотите его кэшировать. Ваша функция не должна принимать ничего, кроме строки в качестве аргумента. Любые аргументы, которые вы передаете, должны оставаться постоянными от вызова к вызову, поэтому что-то вроде «я» будет плохим.

Один простой способ сделать эту работу - встроенная функция, чтобы вам не нужно было передавать что-либо еще кроме ключа. Например:

def index(self):

    # some code here

    # suppose 'place' is a string that you're using as a key. maybe
    # you're caching a description for cities and 'place' would be "New York"
    # in one instance

    @cache_region('long_term', 'place_desc')
    def getDescriptionForPlace(place):
      # perform expensive operation here
      description = ...
      return description

    # this will either fetch the data or just load it from the cache
    description = getDescriptionForPlace(place)

Ваш файл кэша должен выглядеть следующим образом. Обратите внимание, что только «place_desc» и «John» были сохранены в качестве ключа.

tp3 
sS'place_desc John' 
p4
1 голос
/ 10 июля 2010

Попробуйте return list(results) вместо return results и посмотрите, поможет ли это.

Кэш файла буфера должен иметь возможность выбирать и ключи, и значения кеша;большинство итераторов и генераторов не замаскированы.

1 голос
/ 03 июля 2010

Я вижу, что документы beaker не упоминают об этом явно, но, очевидно, функция decorate должна выбирать аргументы, с которыми она вызывается (чтобы использовать как часть ключа в кеше, чтобы проверить, присутствует ли запись и добавить его позже в противном случае) - и, объекты генератора не могут быть засолены, как сообщается в сообщении об ошибке. Это, конечно, означает, что query является объектом-генератором.

То, что вы должны сделать для того, чтобы использовать химический стакан или любой другой вид кеша, - это обойти вместо query объекта-генератора (* pickleable) parameters, из которого этот запрос может быть построен - строки числа, надписи, списки, кортежи и т. д. и т. д., составленные любым удобным для вас способом, а также легко построить запрос из «точно в срок» только в теле функции get_results. Таким образом, аргументы будут выбираться, и кеширование будет работать.

Если это удобно, вы могли бы создать простой перестраиваемый класс, экземпляры которого «поддерживают» запросы, эмулируя любую инициализацию и установку параметров, которые вам требуются, и выполняя инстанцирование точно в срок, только когда какой-то метод, требующий фактического объекта запроса, является называется. Но это всего лишь идея «удобства», и она не меняет основную концепцию, описанную в предыдущем абзаце.

...