Как заставить простую потоковую обработку работать на Python

#python #multithreading #loops #concurrency #python-requests

#python #многопоточность #циклы #параллелизм #python-запросы

Вопрос:

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

 import requests
import sys
import time
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


with open("websites.txt", 'r') as websites:
    websites = websites.read().splitlines()

with open("para1.txt", 'r') as para1:
    para1 = para1.read().splitlines()

with open("para2.txt", 'r') as para2:
   para2 = para2.read().splitlines()

def main():
    for i in para1:
        for j in para2:
            for m in websites:
                try:
                    res = requests.get(m   i   j, verify=False, timeout=10)
                    print(m   i   j)
                    if res.status_code == 200:
                        print('Yes')
                    else:
                        print('No')
                except Exception as e:
                    print(e)
                except KeyboardInterrupt:
                    sys.exit()
                finally:
                    res.close()
                    time.sleep(1)

if __name__ == '__main__':
    main()

 

Ответ №1:

Вы можете применить ThreadPoolExecutor движущуюся часть кода, которая выполняет запросы к отдельной функции и передает ее в качестве аргумента:

 import urllib3
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def check_func(url):
    response = requests.get(url, verify=False, timeout=10)
    return response.status_code == 200
    
def main():
    with open("websites.txt") as website_f, open("para1.txt") as para1_f,
        open("para2.txt", 'r') as para2_f, ThreadPoolExecutor(max_workers=4) as executor:
        tasks = {}
        for website in website_f:
            for para1 in para1_f:
                for para2 in para2_f:
                    url = website.rstrip()   para1.rstrip()   para2.rstrip()
                    tasks[executor.submit(check_func, url)] = url

        for task in as_completed(tasks):
            url = tasks[task]
            try:
                result = task.result()
            except KeyboardInterrupt:  # handling Ctrl   C
                for task in tasks:
                    task.cancel()      # won't cancel already finished or pending futures
            except CancelledError:     # will never happen (normally)
                pass                            
            except Exception as e:
                print(url, "-", "ERROR", e)
            else:
                print(url, "-", "GOOD" if result else "BAD")
        
if __name__ == "__main__":
    main()
 

P.S. Я не тестировал весь код целиком, поэтому, если с ним возникнут какие-либо проблемы — пишите в комментариях.

Комментарии:

1. спасибо за ваш ответ, ну, потоковая обработка работает, и теперь она действительно быстрая, но скрипт больше не работает корректно. Я не знаю почему, но теперь он будет проверять только первую запись из «websites.txt » с первой записью из «para1.txt » до тех пор, пока все записи из «para2.txt » закончено

2. В скрипте без потоковой обработки он будет проверять запись один из «website.txt » с записью один из «para1.txt » и «para2.txt » затем он проверяет запись 2 из «website.txt » с записью один из «para1.txt » и запись 1 из «para2.txt »

3. @tadeu244, измените порядок циклов, чтобы он соответствовал вашему примеру