首页 > 解决方案 > 如何在 x 异常或 403 后计数和停止脚本

问题描述

我一直在尝试学习如何正确编写计数器和“停止器”,例如状态 403 x 连续 10 次,或者如果我连续 10 次遇到连接错误。

现在我做了这样的事情:

import requests
import time
from requests.exceptions import ConnectionError, ReadTimeout, RequestException, Timeout

exception_counter = 0

while True:

    try:
        response = requests.get("https://stackoverflow.com/", timeout=12)

        if response.ok:
            print("Very nice")
            time.sleep(60)

        else:
            print(
                f'[Response -> {response.status_code}]'
                f'[Response Url -> {response.url}]'
            )
            time.sleep(60)

            if response.status_code == 403:
                if exception_counter >= 10:
                    print("Hit limitation of counter: Response [403]")
                    time.sleep(4294968)

                exception_counter += 1

    
    except (ConnectionError) as err:
        print(err)
        time.sleep(random.randint(1, 3))
        
        if exception_counter >= 10:
            print(f"Hit limitation of coonnectionerror {err}")
            time.sleep(4294968)
            continue
        
        exception_counter += 1
        continue
        
    except (ReadTimeout, Timeout) as err:
        print(err)
        time.sleep(random.randint(1, 3))
        continue

    except RequestException as err:
        print(err)
        time.sleep(random.randint(1, 3))
        continue

    except Exception as err:
        print(err)
        time.sleep(random.randint(1, 3))
        
        if exception_counter >= 10:
            print(f"Hit limitation of Exception {err}")
            time.sleep(4294968)
            continue
        
        exception_counter += 1
        continue

但是,我并不担心我在不同地方重复相同代码的地方是否正确。我想知道如何以正确和正确的方式实际做到这一点,与我在不同地方重复相同代码所做的事情相比

编辑:

更新代码:

现在的问题是,每当我们成功打印时,我想重置计数器,但现在没有。

import time

import requests


class ExceptionCounter:
    def __init__(self):
        self.count = 0

    def check(self, message):
        self.count += 1
        print(self.count)
        if self.count > 3:
            print(message, 'exceeded 3 counts')
            time.sleep(6000)


exception_counter = ExceptionCounter()


def main():
    while True:
        response = requests.post("https://www.google.se/")

        print(response.status_code)

        if response.ok:
            print("Yay! Now I want to reset my counter because it got successful!")
        else:
            exception_counter.check(f"Ahhhh, wrong status code! {response.status_code}!")

        time.sleep(1)


main()

标签: pythonpython-3.xexceptioncount

解决方案


requests由 支持urllib3,因此您可以只配置一些内置的重试功能,而不是滚动您自己的计数器。

下面的文章是一个很好的资源,并介绍了一些其他常见的高级用例requests

https://findwork.dev/blog/advanced-usage-python-requests-timeouts-retries-hooks/

这是一个修改后的使用示例。

import logging

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

DEFAULT_TIMEOUT = 12  # seconds


def main():
    logging.basicConfig(level=logging.DEBUG)
    retry_strategy = Retry(
        total=10,
        backoff_factor=1,
        status_forcelist=[403, 429, 500, 502, 503, 504],
    )
    adapter = TimeoutHTTPAdapter(max_retries=retry_strategy)

    http = requests.Session()
    http.mount("https://", adapter)
    http.mount("http://", adapter)

    url = "https://notarealsite.foo/"
    try:
        response = http.get(url)
        response.raise_for_status()
    except RequestException:
        logging.exception(f"Problem with request to {url}")


class TimeoutHTTPAdapter(HTTPAdapter):
    def __init__(self, *args, **kwargs):
        self.timeout = DEFAULT_TIMEOUT
        if "timeout" in kwargs:
            self.timeout = kwargs["timeout"]
            del kwargs["timeout"]
        super().__init__(*args, **kwargs)

    def send(self, request, **kwargs):
        timeout = kwargs.get("timeout")
        if timeout is None:
            kwargs["timeout"] = self.timeout
        return super().send(request, **kwargs)


if __name__ == "__main__":
    main()

这会设置日志DEBUG级别,以便您可以看到重试发生了什么。

我使用了您的超时 12 并添加了 403,但您应该注意 403 不是重试的有效状态。请参阅以下内容以了解原因。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403

HTTP403 Forbidden客户端错误状态响应码表示服务器理解请求但拒绝授权。

此状态类似于401,但在这种情况下,重新认证将没有任何区别。访问被永久禁止并与应用程序逻辑相关联,例如对资源的权限不足。


推荐阅读