Калі некалькі патокаў дзеляць невялікі пул проксі, выбар выпадковага запісу можа даць дзвюм актыўным аперацыям адзін і той жа проксі. Чарга можа ўтрымліваць запісы, якія зараз даступныя для пазычання:

from contextlib import contextmanager
from queue import Queue

available = Queue()
for endpoint in dict.fromkeys(proxy_urls):
    available.put(endpoint)

@contextmanager
def borrow_proxy():
    endpoint = available.get(timeout=5)
    try:
        yield endpoint
    finally:
        available.put(endpoint)

def process_url(url):
    with borrow_proxy() as endpoint:
        return fetch_one(url, endpoint)

Пабудуйце чаргу адзін раз, перад запускам працоўных патокаў. proxy_urls змяшчае поўныя URL канчатковых пунктаў. Публічныя кандыдаты даступныя ў спісе бясплатных проксі; выкарыстоўвайце пратакол і фармат URL, якія падтрымлівае fetch_one. Існуючая сінхронная функцыя fetch_one павінна завяршыць сеткавую аперацыю і закрыць любы адказ перад вяртаннем. Інакш арэнда скончыцца, пакуль злучэнне яшчэ выкарыстоўвае гэты проксі.

Queue.get атамарна выдаляе адзін даступны запіс. Вычарпаны пул чакае, а не шматразова скануе агульныя сцягі. Калі за пяць секунд не прыйдзе ніводны запіс, queue.Empty дасягае таго, хто выклікае; выберыце палітыку паўтору, збою або скасавання праграмы для гэтага выніку.

Блок finally вяртае атрыманы запіс пасля поспеху або выключэння. Ён не абвяшчае, што няўдалы канчатковы пункт здаровы. Палітыкі каранціну, замены і астуджэння патрабуюць яўнага шляху, а не маўклівага адкідання кожнага проксі, які ўбачыў часовую памылку.

Дэдублікацыя аднолькавых радкоў URL прадухіляе дублікаты запісаў у чарзе. Розныя URL могуць па-ранейшаму адносіцца да аднаго фізічнага проксі або выхаду; згуртуйце іх свядома, калі эксклюзіўнасць павінна прымяняцца да гэтага агульнага рэсурсу. Чарга каардынуе патокаў у гэтым працэсе, а не працоўных на іншых машынах.

Падобныя артыкулы