وقتی چند رشته یک استخر کوچک پروکسی را به اشتراک می‌گذارند، انتخاب یک ورودی تصادفی می‌تواند به دو عملیات فعال همان پروکسی را بدهد. صف می‌تواند ورودی‌هایی را نگه دارد که اکنون برای قرض گرفتن در دسترس‌اند:

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های متفاوت هنوز می‌توانند به همان پروکسی فیزیکی یا خروجی اشاره کنند؛ اگر انحصار باید بر آن منبع مشترک اعمال شود، آن‌ها را آگاهانه گروه‌بندی کنید. صف رشته‌های همین فرایند را هماهنگ می‌کند، نه کارگران روی ماشین‌های دیگر.

مقالات مرتبط