Python 请求缓存是否会在信息更新时自动更新缓存?
我使用Python请求了一个非常不可靠的API。我一直在考虑使用Python 请求缓存是否会在信息更新时自动更新缓存?,python,caching,python-requests,Python,Caching,Python Requests,我使用Python请求了一个非常不可靠的API。我一直在考虑使用expire\u,并将其设置为999999999999,就像我见过其他人那样。 唯一的问题是,我不知道当API再次工作时,数据是否更新。如果请求,缓存将自动更新和删除旧条目 我已尝试阅读文档,但我在任何地方都看不到这一点。请求\u缓存将不会更新,直到时间过后过期。在这种情况下,它不会检测到您的API回到工作状态 我注意到该项目后来增加了一个我过去实施的选项;您现在可以在配置缓存时设置old\u data\u on\u error选项
expire\u,并将其设置为999999999999,就像我见过其他人那样。
唯一的问题是,我不知道当API再次工作时,数据是否更新。如果请求,缓存将自动更新和删除旧条目
我已尝试阅读文档,但我在任何地方都看不到这一点。请求\u缓存
将不会更新,直到时间过后过期。在这种情况下,它不会检测到您的API回到工作状态
我注意到该项目后来增加了一个我过去实施的选项;您现在可以在配置缓存时设置old\u data\u on\u error
选项;见:
old\u data\u on\u error–如果True
更新失败,它将返回过期的缓存响应
如果后端更新失败,它将重用现有缓存数据,而不是删除该数据
在过去,我创建了自己的请求\u缓存
会话设置(加上小补丁),如果后端出现500个错误或超时(使用短超时)来处理有问题的API层,则在过期
之后重用缓存值,而不是依赖过期
:
import logging
from datetime import (
datetime,
timedelta
)
from requests.exceptions import (
ConnectionError,
Timeout,
)
from requests_cache.core import (
dispatch_hook,
CachedSession,
)
log = logging.getLogger(__name__)
# Stop logging from complaining if no logging has been configured.
log.addHandler(logging.NullHandler())
class FallbackCachedSession(CachedSession):
"""Cached session that'll reuse expired cache data on timeouts
This allows survival in case the backend is down, living of stale
data until it comes back.
"""
def send(self, request, **kwargs):
# this *bypasses* CachedSession.send; we want to call the method
# CachedSession.send() would have delegated to!
session_send = super(CachedSession, self).send
if (self._is_cache_disabled or
request.method not in self._cache_allowable_methods):
response = session_send(request, **kwargs)
response.from_cache = False
return response
cache_key = self.cache.create_key(request)
def send_request_and_cache_response(stale=None):
try:
response = session_send(request, **kwargs)
except (Timeout, ConnectionError):
if stale is None:
raise
log.warning('No response received, reusing stale response for '
'%s', request.url)
return stale
if stale is not None and response.status_code == 500:
log.warning('Response gave 500 error, reusing stale response '
'for %s', request.url)
return stale
if response.status_code in self._cache_allowable_codes:
self.cache.save_response(cache_key, response)
response.from_cache = False
return response
response, timestamp = self.cache.get_response_and_time(cache_key)
if response is None:
return send_request_and_cache_response()
if self._cache_expire_after is not None:
is_expired = datetime.utcnow() - timestamp > self._cache_expire_after
if is_expired:
self.cache.delete(cache_key)
# try and get a fresh response, but if that fails reuse the
# stale one
return send_request_and_cache_response(stale=response)
# dispatch hook here, because we've removed it before pickling
response.from_cache = True
response = dispatch_hook('response', request.hooks, response, **kwargs)
return response
def basecache_delete(self, key):
# We don't really delete; we instead set the timestamp to
# datetime.min. This way we can re-use stale values if the backend
# fails
try:
if key not in self.responses:
key = self.keys_map[key]
self.responses[key] = self.responses[key][0], datetime.min
except KeyError:
return
from requests_cache.backends.base import BaseCache
BaseCache.delete = basecache_delete
CachedSession
的上述子类绕过,而直接转到原始的requests.Session.send()
方法,以返回现有的缓存值,即使超时已过但后端失败。删除被禁用,以便将超时值设置为0,因此,如果新请求失败,我们仍然可以重用旧值
使用FallbackCachedSession
而不是常规的CachedSession
对象
如果要使用请求缓存。安装缓存()
,请确保在会话工厂中的关键字参数中将FallbackCachedSession
传递给该函数:
import requests_cache
requests_cache.install_cache(
'cache_name', backend='some_backend', expire_after=180,
session_factory=FallbackCachedSession)
我的方法比我破解上述内容一段时间后实现的requests\u cache
更全面一些;我的版本将退回到过时的响应,即使您以前明确将其标记为已删除。尝试执行类似操作:
class UnreliableAPIClient:
def __init__(self):
self.some_api_method_cached = {} # we will store results here
def some_api_method(self, param1, param2)
params_hash = "{0}-{1}".format(param1, param2) # need to identify input
try:
result = do_call_some_api_method_with_fail_probability(param1, param2)
self.some_api_method_cached[params_hash] = result # save result
except:
result = self.some_api_method_cached[params_hash] # resort to cached result
if result is None:
raise # reraise exception if nothing cached
return result
当然,你可以用它来做一个简单的装饰,这取决于你-这看起来就是我需要的!所以我只是把它当作一个请求\u缓存来使用。安装\u缓存('cache',backend='sqlite',expire\u after=180)
(我是否更改expire\u after
?)@onlyonearound:请求\u缓存。安装\u缓存()
修补请求
以使用正常的缓存会话
;这可不行。请稍等,我将快速创建一个版本。@TheOnlyOneAround:添加了如何传入新的缓存会话版本。@TheOnlyOneAround:我注意到项目已经添加了自己的陈旧数据重用选项;我已经更新了我的答案以反映这一点(当我编写上述方法时,它不可用)。这两种方法都有优点,而且都有效,但我的方法在保持陈旧数据可重用性方面更积极一些。人力资源管理,如果我包括超时,这似乎不起作用,你能解决这个问题吗?很抱歉反应太晚。