使用requests/urllib3在每次重试尝试时添加回调函数

2024-03-28 14:16:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经使用^{}实现了对requests会话的重试机制,正如建议的here和{a3}。在

现在,我正在尝试找出添加回调函数的最佳方法,该函数将在每次重试尝试时被调用。在

为了更详细地解释我自己,如果Retry对象或requestsget方法都能添加回调函数,那就太好了。可能是这样的:

import requests
from requests.packages.urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter

def retry_callback(url):
    print url   

s = requests.Session()
retries = Retry(total=5, status_forcelist=[ 500, 502, 503, 504 ])
s.mount('http://', HTTPAdapter(max_retries=retries))

url = 'http://httpstat.us/500'
s.get(url, callback=retry_callback, callback_params=[url])

我知道对于打印url,我可以使用日志记录,但这只是一个简单的例子,用于更复杂的用途。
请原谅,如果这不是最好的python编码,但我希望它足够清楚。在

谢谢。在


Tags: 方法函数fromimporthttpurlherecallback
1条回答
网友
1楼 · 发布于 2024-03-28 14:16:14

您可以将Retry类的子类化以添加该功能。在

这是给定连接尝试中与Retry实例的完整交互流:

  • ^每当引发异常、返回30倍重定向响应或Retry.is_retry()方法返回true时,将使用当前方法、url、响应对象(如果有)和异常(如果引发了一个)调用{}。
    • .increment()将重新引发错误(如果有),并且该对象被配置为不重试该特定类别的错误。在
    • .increment()调用Retry.new()创建一个更新的实例,更新任何相关的计数器,并用新的^{} instance(命名元组)修改{}属性。在
    • ^如果对Retry.new()的返回值调用.increment()为true,则{}将引发MaxRetryError异常。is_exhausted()当它跟踪的任何计数器低于0时返回true(忽略设置为None的计数器)。在
    • .increment()返回新的Retry实例。在
  • Retry.increment()的返回值将替换跟踪的旧的Retry实例。如果有重定向,则调用Retry.sleep_for_retry()(如果存在Retry-After头,则为休眠),否则调用Retry.sleep()(调用self.sleep_for_retry()以遵守Retry-After头,否则只在有退避策略时休眠)。然后使用新的Retry实例进行递归连接调用。在

这为您提供了3个好的回调点:在.increment()开始时,在创建新的Retry实例时,以及在{}周围的上下文管理器中,允许回调否决异常或在退出时更新返回的重试策略。在

将钩子放在.increment()的开头是这样的:

import logging

logger = getLogger(__name__)

class CallbackRetry(Retry):
    def __init__(self, *args, **kwargs):
        self._callback = kwargs.pop('callback', None)
        super(CallbackRetry, self).__init__(*args, **kwargs)
    def new(self, **kw):
        # pass along the subclass additional information when creating
        # a new instance.
        kw['callback'] = self._callback
        return super(CallbackRetry, self).new(**kw)
    def increment(self, method, url, *args, **kwargs):
        if self._callback:
            try:
                self._callback(url)
            except Exception:
                logger.exception('Callback raised an exception, ignoring')
        return super(CallbackRetry, self).increment(method, url, *args, **kwargs)

注意,url参数实际上只是URL path,请求的net location部分被省略了(您必须从_pool参数中提取它,它有.scheme.host.port属性)。在

演示:

^{pr2}$

.new()方法中放置一个钩子可以让您为下一次尝试调整策略,也可以让您反思.history属性,但不能避免异常重新引发。在

相关问题 更多 >