Многопоточные запросы Python3

Я много исследовал эту тему, но проблема в том, что я не могу понять, как отправлять многопоточные почтовые запросы с помощью python3.

names = ["dfg","dddfg","qwed"]

for name in names :
    res = requests.post(url,data=name)
    res.text 

Здесь я хочу отправить все эти имена, и я хочу использовать многопоточность, чтобы сделать это быстрее.


person For This    schedule 25.05.2020    source источник
comment
Лучше использовать asyncio и aiohttp для python 3.   -  person bigbounty    schedule 25.05.2020
comment
+1 @bigbounty. Я не могу не подчеркнуть это достаточно. ОП, проверьте это.   -  person Felipe    schedule 26.05.2020


Ответы (1)


Решение 1. concurrent.futures.ThreadPoolExecutor определить количество потоков

С помощью пользовательской функции (request_post) вы можете делать практически все.

import concurrent
import requests

def request_post(url, data):
    return requests.post(url, data=data)

with concurrent.futures.ThreadPoolExecutor() as executor: # optimally defined number of threads
    res = [executor.submit(request_post, url, data) for data in names]
    concurrent.futures.wait(res)

res будет список request.Response для каждого запроса, сделанного в Future экземплярах. . Чтобы получить доступ к request.Response, вам нужно использовать res[index].result(), где index размер равен len(names).

Будущие объекты дают вам лучший контроль над полученными ответами, например, правильно ли они завершились, было ли исключение или тайм-аут и т. д. Подробнее о здесь

Вы не рискуете столкнуться с проблемами, связанными с большим количеством потоков (решение 2).


Решение 2. multiprocessing.dummy.Pool и создание одного потока для каждого запроса

Может быть полезно, если вы не запрашиваете много страниц, а также если время отклика довольно медленное.

from multiprocessing.dummy import Pool as ThreadPool
import itertools
import requests

with ThreadPool(len(names)) as pool: # creates a Pool of 3 threads 
    res = pool.starmap(requests.post(itertools.repeat(url),names))

pool.starmap — используется для передачи (map) нескольких аргументов в одну функцию (requests.post), которая будет вызываться списком потоков (ThreadPool). Он вернет список request.Response для каждого сделанного запроса.

intertools.repeat(url) необходимо, чтобы первый аргумент повторялся в том же количестве создаваемых потоков.

names — это второй аргумент requests.post, поэтому он будет работать без необходимости явно использовать необязательный параметр data. Его len должен совпадать с количеством создаваемых потоков.

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

person eusoubrasileiro    schedule 25.05.2020
comment
На самом деле, вы можете добавить комментарии, которые не так известны python прямо сейчас, чтобы я мог понять этот код немного больше, чем то, что на самом деле делает какая часть. - person For This; 25.05.2020
comment
Может быть, этот второй будет работать, но я понятия не имею, как я могу реализовать его здесь. - person For This; 25.05.2020
comment
в то время как я ‹ len(name): print(i,idx) try: loadproxy = { https:https://+proxys[idx], } myobj= {name:name[i],stats:playerStats[i]} res = request.post(url, json = myobj,proxy=loadproxy,timeout=100) i+=1 idx+=1 if(SuccessKey): if(SuccessKey в res.text): print(res.text) else: print(Can не добавлять Failed) elif(FailureKey): if(FailureKey не в res.text): print(res.text) else: print(Невозможно добавить Failed) кроме Exception as e: print(Что-то пошло не так) idx+=1 Продолжать - person For This; 25.05.2020
comment
Если вы можете направить это будет полезно - person For This; 25.05.2020
comment
Можете ли вы опубликовать эти подробные требования в теле вопроса? Я совершенно не понимаю вашу проблему, которую вы пытаетесь решить. - person eusoubrasileiro; 25.05.2020
comment
Давайте продолжим это обсуждение в чате. - person eusoubrasileiro; 25.05.2020
comment
Обратите внимание, что с параллельными фьючерсами как ThreadPool (который вы хотите использовать для задач, связанных с вводом-выводом, подобных этой), так и ProcessPool имеют значения по умолчанию для количества рабочих, которые обычно работают довольно оптимально. Таким образом, в приведенном выше примере concurrent.futures вы можете оставить счетчик рабочих операций пустым и наилучшим образом использовать ресурсы: с concurrent.futures.ThreadPoolExecutor() в качестве исполнителя: см. docs.python.org/3/library/concurrent.futures.html - person Richard; 26.05.2020
comment
спасибо @Richard, ты прав. Я прокомментирую это в ответ. - person eusoubrasileiro; 26.05.2020