【问题标题】:Python requests with HTTPAdapter is halting for hours带有 HTTPAdapter 的 Python 请求暂停了几个小时
【发布时间】:2018-05-04 00:29:55
【问题描述】:

我有一个特殊的 URL,我的代码在该 URL 中停止了几个小时(超过 3 小时)。我似乎无法理解它为什么会那样做。

网址是http://www.etudes.ccip.fr/maintenance_site.php

Direct requests.get() 可以立即工作,但每当我有一个 HTTPAdapter 时,代码似乎几乎无限期地休眠

import requests
from requests.adapters import HTTPAdapter    

url = 'http://www.etudes.ccip.fr/maintenance_site.php'
session = requests.Session()
session.mount('http://', HTTPAdapter(max_retries=2))
session.get(url, timeout=2)

【问题讨论】:

  • 你有什么版本的 Python?代码适用于 Ubuntu 上的 Python 2.7.12。服务器响应 url 的 status_code=503。
  • @fast_cen,我知道你已经接受了答案。但我相信正确的做法是禁用重试,而不是禁用重试标头

标签: python python-requests urllib3


【解决方案1】:

您初始化的适配器在下面设置重试

    if max_retries == DEFAULT_RETRIES:
        self.max_retries = Retry(0, read=False)
    else:
        self.max_retries = Retry.from_int(max_retries)

如果你看一下初始化

def __init__(self, total=10, connect=None, read=None, redirect=None, status=None,
             method_whitelist=DEFAULT_METHOD_WHITELIST, status_forcelist=None,
             backoff_factor=0, raise_on_redirect=True, raise_on_status=True,
             history=None, respect_retry_after_header=True):

respect_retry_after_header 的默认值为True。你需要这个False。如果您使用 curl 检查响应

$ curl -I http://www.etudes.ccip.fr/maintenance_site.php
HTTP/1.1 503 Service Temporarily Unavailable
Date: Thu, 23 Nov 2017 14:15:49 GMT
Server: Apache
Status: 503 Service Temporarily Unavailable
Retry-After: 3600
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Cache-Control: pre-check=0, post-check=0, max-age=0
Pragma: no-cache
Connection: close
Content-Type: text/html; charset=ISO-8859-1

您希望将 respect_retry_after_header 设置为 False。这可以通过创建适配器然后修改此行为来完成

import requests
from requests.adapters import HTTPAdapter

url = 'http://www.etudes.ccip.fr/maintenance_site.php'
session = requests.Session()

adapter = HTTPAdapter(max_retries=2)
adapter.max_retries.respect_retry_after_header = False

session.mount('http://', adapter)

session.get(url, timeout=2)

【讨论】:

    【解决方案2】:

    响应中的 retry-after 标头是将连接设置为休眠 3600 秒的问题。请参阅 urllib3 中的 retry.py。

        def sleep(self, response=None):
        """ Sleep between retry attempts.
    
        This method will respect a server's ``Retry-After`` response header
        and sleep the duration of the time requested. If that is not present, it
        will use an exponential backoff. By default, the backoff factor is 0 and
        this method will return immediately.
        """
    
        if response:
            slept = self.sleep_for_retry(response)
            if slept:
                return
    
        self._sleep_backoff()
    

    解决方法是设置 max_retries=0。这样可以避免 2x3600 秒等待您的应用程序结束。

    【讨论】:

      【解决方案3】:

      正如 Mylsal 所说,尝试设置 max_entries

      session.mount('http://', HTTPAdapter(max_retries=0))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-12
        • 2020-07-26
        • 1970-01-01
        相关资源
        最近更新 更多