Как я могу использовать запросы в asyncio?
Я хочу выполнять параллельные задачи запроса http в asyncio
, но обнаруживаю, что python-requests
блокирует цикл событий asyncio
. Я нашел aiohttp, но не смог предоставить службу http-запроса с помощью http-прокси.
Итак, я хочу знать, есть ли способ сделать асинхронные http-запросы с помощью asyncio
.
Ответы
Ответ 1
Чтобы использовать запросы (или любые другие блокирующие библиотеки) с помощью asyncio, вы можете использовать BaseEventLoop.run_in_executor для запуска функции в другом потоке и получения от него получить результат. Например:
import asyncio
import requests
@asyncio.coroutine
def main():
loop = asyncio.get_event_loop()
future1 = loop.run_in_executor(None, requests.get, 'http://www.google.com')
future2 = loop.run_in_executor(None, requests.get, 'http://www.google.co.uk')
response1 = yield from future1
response2 = yield from future2
print(response1.text)
print(response2.text)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Это даст оба ответа параллельно.
С помощью python 3.5 вы можете использовать новый синтаксис await
/async
:
import asyncio
import requests
async def main():
loop = asyncio.get_event_loop()
future1 = loop.run_in_executor(None, requests.get, 'http://www.google.com')
future2 = loop.run_in_executor(None, requests.get, 'http://www.google.co.uk')
response1 = await future1
response2 = await future2
print(response1.text)
print(response2.text)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Подробнее см. PEP0492.
Ответ 2
aiohttp можно использовать с прокси-сервером HTTP уже:
import asyncio
import aiohttp
@asyncio.coroutine
def do_request():
proxy_url = 'http://localhost:8118' # your proxy address
response = yield from aiohttp.request(
'GET', 'http://google.com',
proxy=proxy_url,
)
return response
loop = asyncio.get_event_loop()
loop.run_until_complete(do_request())
Ответ 3
В настоящее время запросы не поддерживают asyncio
, и нет такой поддержки. Вероятно, вы могли бы реализовать пользовательский "Транспортный адаптер" (как обсуждалось здесь), который знает, как использовать asyncio
.
Если я нахожусь с некоторым временем, это то, над чем я мог бы заглянуть, но я ничего не могу обещать.
Ответ 4
В статье Пимина Константина Кефалукоса есть хороший пример циклов асинхронного/ждущего и потокового
Простые параллельные HTTP-запросы с Python и асинхронным:
Чтобы минимизировать общее время завершения, мы могли бы увеличить размер пула потоков, чтобы соответствовать количеству запросов, которые мы должны выполнить. К счастью, это легко сделать, как мы увидим дальше. Ниже приведен код, приведенный ниже, как сделать двадцать асинхронных HTTP-запросов с пулом потоков из двадцати рабочих потоков:
# Example 3: asynchronous requests with larger thread pool
import asyncio
import concurrent.futures
import requests
async def main():
with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
loop = asyncio.get_event_loop()
futures = [
loop.run_in_executor(
executor,
requests.get,
'http://example.org/'
)
for i in range(20)
]
for response in await asyncio.gather(*futures):
pass
loop = asyncio.get_event_loop()
loop.run_until_complete(main())