#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, измените порядок циклов, чтобы он соответствовал вашему примеру