@VitaliyShvets

Как добавить Critical section в код?

Есть такой скрипт, который читает ссылки с файла и делает и делает запрос по каждой, а затем выводит код ответа и url. Но если ответ равен 301(редирект), то нужно проверить и ссылку на которую нас перенаправляют и вывести соответствующий текст.
import concurrent.futures
import requests
import threading
import time
import sys 

thread_local = threading.local()

lock = threading.Lock()

def get_session():
    if not hasattr(thread_local, "session"):
        thread_local.session = requests.Session()
    return thread_local.session


def check(url,r=0):
    session = get_session()
    try:
        with session.head(url[:-1], timeout=8) as response:
            if r==1:
                print("   -> ", response.status_code, " - ", url)
            else:
                print(response.status_code," - ",url[:-1])

            if response.status_code == 301:
                #Тут должна начинаться критическая  секция
                check(response.headers['Location'], 1)
                 
                return
        return
    except IOError:
        print("XXX - ", url[:-1])
        pass    

def check_all(sites):
    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        executor.map(check, sites)


if __name__ == "__main__":


    sites = [] 
    
    wordlist=sys.argv[1]
    a=open(wordlist,"r").readlines()

    for url in a:
       if "http" not in url or "https" not in url:
           sites.append("http://"+str(url))
    
    start_time = time.time()
    check_all(sites)
    duration = time.time() - start_time
    print(f"Check {len(sites)} in {duration} seconds")


Нужно сделать так, чтобы при проверке редирект ссылки не было прерывания на другой поток, потому что вывод получается некоректный:

301 - http://site.com
200 - http://site2.com
   -> 200 - https://site.com/


Нужно чтобы было так:
301 - http://site.com
    -> 200 - https://site.com/
200 - http://site2.com
  • Вопрос задан
  • 172 просмотра
Пригласить эксперта
Ответы на вопрос 1
@mrxor
Simple is better than complex
lock.acquire()
check(response.headers['Location'], 1)
lock.release()

Плюс нужно еще отпускать лок в случае ошибки.
Минус такого решения в том, что треды и так блокируют друг друга из-за Gil, а тут еще лок добавляется.
Лучше сделать через мультипроцессинг или (еще лучше) переписать на переписать на asyncio + aiohttp
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы