<p><code>requests_cache</code>在<code>expire_after</code>时间过去之前,<code>requests_cache</code>不会更新。在这种情况下,你的API将检测不回工作状态。在</p>
<p>我注意到项目已经添加了一个我在过去实现的选项;现在您可以在配置缓存时设置<code>old_data_on_error</code>选项;请参见<a href="http://requests-cache.readthedocs.org/en/latest/api.html#requests_cache.core.CachedSession" rel="nofollow">^{<cd4>} documentation</a>:</p>
<blockquote>
<p><strong>old_data_on_error</strong> – If <code>True</code> it will return expired cached response if update fails.</p>
</blockquote>
<p>如果后端更新失败,它将重用现有的缓存数据,而不是删除这些数据。在</p>
<p>过去,我创建了自己的<code>requests_cache</code>会话设置(加上小补丁),如果后端出现500个错误或超时(使用短超时)来处理有问题的API层,则会在<code>expire_after</code>之外重用缓存值,而不是依赖<code>expire_after</code>:</p>
<pre><code>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
</code></pre>
<p>上面的<code>CachedSession</code>子类绕过了<a href="https://github.com/reclosedev/requests-cache/blob/master/requests_cache/core.py#L83-L121" rel="nofollow">original ^{<cd9>} method</a>,而是直接转到原始的<code>requests.Session.send()</code>方法,以返回现有的缓存值,即使超时已过,但后端已失败。为了将超时值设置为0,删除被禁用,因此如果新请求失败,我们仍然可以重用旧值。在</p>
<p>使用<code>FallbackCachedSession</code>而不是常规的<code>CachedSession</code>对象。在</p>
<p>如果要使用<code>requests_cache.install_cache()</code>,请确保在<code>session_factory</code>关键字参数中将{<cd11>}传递给该函数:</p>
^{pr2}$
<p>我的方法比在我把上面的代码组合在一起一段时间后实现的<code>requests_cache</code>要全面一些;我的版本将返回到一个过时的响应中,即使您之前明确地将其标记为deleted。在</p>