有一个电报机器人根据时间表发送报价。添加到其lru_cache通过functools.
结果,用户收到了 3 次相同的报价(在不同的时间),尽管cache_clear()我在每次邮寄后都收到了。引号取自 MongoDB,这是我想要缓存的时刻,这样它就不会花一秒钟的时间。
class Quote:
@lru_cache(maxsize=19)
def check(self, user: str, check=True) -> dict:
"""Checks for quote available for {user}"""
est_quotes = self.db.estimated_document_count()
if self.db.count_documents({"Users": user}) >= est_quotes - 1:
# removes user id from DB if there is no more available quotes for user
self.db.update_many({"Users": user}, {"$pull": {"Users": user}})
all_quotes = self.db.find({})
while True:
quote = all_quotes[random.randint(0, est_quotes - 1)]
if not check:
# if check for available is not required return random quote
return quote
if user in quote["Users"]:
continue
required_quote = quote
self.db.update_one({"Quote": quote["Quote"]}, {"$push": {"Users": user}})
return required_quote
def random(self, user, checking=False):
""" Sends random quote for user.
If checking == False, it does not check for the presence of id in the database.
"""
quo = self.check(user, check=checking)
keyboard = types.InlineKeyboardMarkup()
key_book = types.InlineKeyboardButton(text='📖', callback_data='book', url=quo["URL"])
keyboard.add(key_book)
# key_like = types.InlineKeyboardButton(text='Нет', callback_data='no')
# keyboard.add(key_like)
bot.send_message(user,
text=f'<i>{quo["Quote"]}\n</i>\n<b>{quo["Book"]}</b>\n#{quo["Author"]}',
parse_mode='HTML', reply_markup=keyboard)
def randoms(self, group: int):
"""Sends random quote for users who aren't in 'stopped' list"""
start_time = time.time()
counter = 0
with open(f'users{group}', 'r') as users_r:
r = users_r.read().splitlines()
print("=================================")
for user_id in r:
if user_id in self.stopped:
continue
try:
self.random(str(user_id), True)
print(f"Latency #{counter}: {str(time.time() - start_time)[:4]} seconds")
except telebot.apihelper.ApiTelegramException as e:
print(f"Bad ID ({user_id}):", e)
except Exception as e:
print(e)
finally:
counter += 1
self.check.cache_clear()
很可能,我只是不太了解缓存的方式和内容,但我请您为我的问题提出最佳解决方案。
缓存装饰器
functools的目的是在使用相同参数调用装饰函数时从缓存中返回相同的结果。那些。在您的情况下,如果我们
.check(user="user1")使用相同的参数值连续调用该方法 18 次user,那么我们将获得18 次相同的结果。在我看来,这显然违背了您的意图,并且
lru_cache在您的情况下是错误的工具。PS 通常缓存装饰器用于确定性函数,但不适用于返回随机结果的函数。