Как повторить инструкцию try за определенное количество попыток - PullRequest
1 голос
/ 12 июля 2020

В настоящее время у меня есть программа, которая имеет прокси и делает запрос на получение моего IP-адреса с помощью этого прокси и возвращает его обратно в json.

Пример обратного запроса:

Got Back: {'ip': '91.67.240.45', 'country': 'Germany', 'cc': 'DE'}

Я хочу, чтобы моя программа попыталась сделать запрос по URL-адресу, и если она не получит запрос из-за того, что прокси не работает, я хочу повторить попытку 5 раз, прежде чем перейти на следующий IP-адрес .

Я думал, что этот блок except будет работать, но он не выходит из l oop, когда 5 итераций завершены, и я не уверен, почему.

Моя программа, тем не менее, работает когда прокси включен для первой попытки, так как после первой попытки он ломается, а затем переходит на следующий IP-адрес.

Вот что у меня сейчас есть:

import requests
import time

proxies = [
    "95.87.220.19:15600",
    "91.67.240.45:3128",
    "85.175.216.32:53281",
    "91.236.251.131:8118",
    "91.236.251.131:8118",
    "88.99.10.249:1080",
]


def sol(ip):
    max_tries = 5
    for i in range(1, max_tries+1):
        try:
            print(f"Using Proxy: {ip}")
            r = requests.get('https://api.myip.com', proxies={"https": ip})
            print(f"Got Back: {r.json()}")
            break
        except OSError:
            time.sleep(5)
            print(f"Retrying...: {i}")
        break


for i in proxies:
    sol(i)

Как я могу сделать это мой l oop имеет 5 попыток перед переходом на следующий IP-адрес.

Ответы [ 3 ]

1 голос
/ 12 июля 2020

Если я правильно понял, можно просто убрать break из последней строки. Если у вас есть безусловный break в al oop, он всегда будет повторяться один раз.

def sol(ip):
    max_tries = 5
    for i in range(1, max_tries+1):
        try:
            print(f"Using Proxy: {ip}")
            r = requests.get('https://api.myip.com', proxies={"https": ip})
            print(f"Got Back: {r.json()}")
            break
        except OSError:
            time.sleep(5)
            print(f"Retrying...: {i}")
        # break                      <---- Remove this line
1 голос
/ 12 июля 2020

Использование повторная попытка будет выглядеть примерно так:

from retrying import retry
import requests

@retry(stop_max_attempt_number=5)
def bad_host():
    print('trying get from bad host')
    return requests.get('https://bad.host.asdqwerqweo79ooo/')

try:
    bad_host()
except IOError as ex:
    print(f"Couldn't connect because: {str(ex)}")

..., что даст следующий результат:

trying get from bad host
trying get from bad host
trying get from bad host
trying get from bad host
trying get from bad host
Couldn't connect to bad host because: HTTPSConnectionPool(host='bad.host.asdqwerqweo79ooo', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x10b6bd910>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known'))

Притягательность

Если вы хотите пофантазировать, вы также можете добавить такие вещи, как экспоненциальный откат и выборочный повтор определенных исключений.

Вот пример:

import random
import time

def retry_ioerror(exception):
    return isinstance(exception, IOError)

@retry(
    wait_exponential_multiplier=100,
    wait_exponential_max=1000,
    retry_on_exception=retry_ioerror,
    stop_max_attempt_number=10)
def do_something():
    t = time.time()
    print(f'trying {t}')
    r = random.random()
    if r > 0.9:
        return 'yay!'
    if r > 0.8:
        raise RuntimeError('Boom!')
    else:
        raise IOError('Bang!')

try:
    result = do_something()
    print(f'Success! {result}')
except RuntimeError as ex:
    print(f"Failed: {str(ex)}")
1 голос
/ 12 июля 2020

Моя программа, однако, работает, когда прокси-сервер включен для первой попытки, так как после первой попытки он прерывается, а затем переходит на следующий IP-адрес.

Это происходит безусловно , потому что после блока except стоит безусловный break. Код продолжает проходить мимо try / except, когда вводится except, при условии, что он не имеет собственного аварийного выхода (другое исключение, return et c.).

Итак,

Я думал, что этот блок except будет работать, но он не выходит из l oop, когда 5 итераций завершены, и я не уверен, почему.

Он не выходит из строя «после того, как 5 итераций завершены», потому что он выходит из строя после первой итерации, независимо от того, была ли эта попытка успешной.

...