Python 请求 - 重试任何状态代码但不是 400

fso*_*ety 4 python-3.x python-requests

我正在使用以下代码段(请注意,仅显示了部分代码段):

from urllib3.util import Retry
status_forcelist = (500, 502, 504)


retry = Retry(
        total=retries,
        read=retries,
        connect=retries,
        backoff_factor=backoff_factor,
        status_forcelist=status_forcelist,
        method_whitelist=frozenset(['GET', 'POST'])
Run Code Online (Sandbox Code Playgroud)

截至目前,将重试状态代码500, 502, 504。但是,我打算重试任何状态代码而不是400. 有没有一种优雅的方法来实现这一点,而不是status_forcelist为所有状态代码填充/硬编码?

zwe*_*wer 6

status_forcelist不幸的是,它仅适用于白名单(鉴于用途,它可以称为黑名单),因此没有内置方法可以优雅地执行此操作。但是,您可以覆盖(或猴子补丁,如果您喜欢的话)urllib3.util.retry.Retry.is_retry()将其视为黑名单,例如:

import urllib3.util.retry

class BlacklistRetry(urllib3.util.retry.Retry):

    def is_retry(self, method, status_code, has_retry_after=False):
        if not self._is_method_retryable(method):
            return False

        if self.status_forcelist and status_code not in self.status_forcelist:
            # threat as a blacklist --------------^
            return True

        return (self.total and self.respect_retry_after_header and
                has_retry_after and (status_code in self.RETRY_AFTER_STATUS_CODES))
Run Code Online (Sandbox Code Playgroud)

然后使用它代替原来的Retry并添加400到它的status_forcelist.


Pat*_*ner 5

您可以从request模块中获取代码- 这样可以节省您将它们写出来的时间。如果有任何新的介绍,您也会拥有它们:

import requests
from urllib3.util import Retry

status_forcelist = tuple( x for x in requests.status_codes._codes if x != 400)

print(status_forcelist)
Run Code Online (Sandbox Code Playgroud)

输出:

(100, 101, 102, 103, 122, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 
 303, 304, 305, 306, 307, 308, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 
 413, 414, 415, 416, 417, 418, 421, 422, 423, 424, 425, 426, 428, 429, 431, 444, 449, 450, 
 451, 499, 500, 501, 502, 503, 504, 505, 506, 507, 509, 510, 511)
Run Code Online (Sandbox Code Playgroud)

警告维基百科列出了“自己创建的”/非官方状态代码以及 9xx 周围的专有状态代码,但此列表并未涵盖这些代码。@zwer 解决方案也将涵盖这些。

  • @amirA 很抱歉这么晚才回答,我没注意到你的问题。它不在其中,因为在回答 104 时,在我使用的版本“requests”中,“requests.status_codes”中没有内容。它只会反映其中的内容 - 请参阅问题前两年添加的_Caveat_评论。 (2认同)