Django: AttributeError: объект 'bool' не имеет атрибута 'expire'

В настоящее время я использую модуль redis.py Энди Маккарди для взаимодействия с Redis из Django.

Я переношу определенные задачи в фоновый режим с помощью Celery.

Вот одна из моих задач:

import redis
pool = redis.ConnectionPool(host='XX.XXX.XXX.X', port=6379, db=0, password='password')
r_server = redis.Redis(connection_pool=pool)
pipe = r_server.pipeline()

# The number of seconds for two months
seconds = 5356800

@shared_task
def Activity(userID, object_id, timestamp):
        timestamp = int(timestamp)
        # Create Individual activity for each.
        activity_key = 'invite:activity:%s:%s' % (userID, timestamp)
        mapping = dict(
            user_id = userID,
            object_id = object_id)
        pipe.hmset(activity_key, mapping).expire(activity_key, seconds).execute()

Всякий раз, когда эта задача вызывается, я получаю следующую ошибку:

AttributeError: 'bool' object has no attribute 'expire'

Что может быть причиной этого?

Позже я провел тест в консоли Python, чтобы увидеть, что с моим синтаксисом что-то не так, но все сработало именно так, как я планировал. Так что же может быть причиной этой ошибки?

ОБНОВЛЕНИЕ

Я думаю, что срок действия оценивает результат hmset (activity_key, mapping). Это странно! expire — это метод для канала.

ВТОРОЕ ОБНОВЛЕНИЕ

Я нашел работу вокруг на данный момент. Кажется, это происходит только внутри Celery. Собственные представления Django и консоль Python не демонстрируют такого поведения. Кажется, он оценивает результат выражения перед ним. Если кто-то из вас столкнется с этой проблемой, вот обходной путь.

pipe.hmset(activity_key, mapping)
pipe.lpush('mylist', 1)
pipe.expire('mylist', 300)
pipe.execute()

Это должно работать и не доставлять вам никаких проблем. Удачного кодирования!


person deadlock    schedule 23.03.2014    source источник


Ответы (1)


pipe.hmset() не возвращает конвейер; вы не можете связывать вызовы здесь. Вместо этого возвращается логическое значение (вероятно, указывающее на успешность вызова hmset()).

Вызовите методы .expire() и .execute() по отдельности:

pipe.hmset(activity_key, mapping)
pipe.expire(activity_key, seconds)
pipe.execute()

Я подозреваю, что вам нужно создать конвейер в задаче Celery вместо повторного использования глобального здесь. Переместите pipe = r_server.pipeline() в действие.

person Martijn Pieters    schedule 23.03.2014
comment
Когда я обновил свой вопрос, чтобы показать свои выводы о том, что сработало, вы ответили в точное время! Я отмечу ваш ответ как правильный ответ. - person deadlock; 23.03.2014
comment
Кроме того, такое поведение происходит только в Celery. Попробовал через консоль, работает. - person deadlock; 23.03.2014
comment
Да; обычно методы Pipeline должны быть связаны цепочкой, что заставляет меня немного задуматься, что здесь происходит. - person Martijn Pieters; 23.03.2014
comment
да, именно этим я и занимаюсь. У меня есть pipe = r_server.pipeline() в качестве глобальной переменной, но почему это вызывает проблемы? - person deadlock; 23.03.2014
comment
Объект pipeline имеет состояние, например, вам действительно не следует делиться этим состоянием между потоками. - person Martijn Pieters; 23.03.2014
comment
Мартейн, теперь я понимаю! спасибо! Думаю, я также могу использовать pipe.reset() после инструкции execute() правильно? - person deadlock; 28.03.2014
comment
Нет, если у вас есть несколько потоков, использующих этот один глобальный объект канала. pipe.reset() подходит, если вы можете гарантировать последовательный доступ. - person Martijn Pieters; 28.03.2014