[python] asyncio에서 요청을 어떻게 사용할 수 있습니까?

에서 병렬 http 요청 작업을 수행하고 asyncio싶지만 python-requests이벤트 루프를 차단할 수 asyncio있습니다. aiohttp를 찾았 지만 http 프록시를 사용하여 http 요청 서비스를 제공 할 수 없습니다.

따라서 .NET의 도움으로 비동기 http 요청을 수행하는 방법이 있는지 알고 싶습니다 asyncio.



답변

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에서는 new 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 를 참조하십시오 .


답변

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())


답변

위의 답변은 여전히 ​​오래된 Python 3.4 스타일 코 루틴을 사용하고 있습니다. 다음은 Python 3.5 이상을 사용하는 경우 작성하는 내용입니다.

aiohttp 이제 http 프록시 지원

import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
            'http://python.org',
            'https://google.com',
            'http://yifei.me'
        ]
    tasks = []
    async with aiohttp.ClientSession() as session:
        for url in urls:
            tasks.append(fetch(session, url))
        htmls = await asyncio.gather(*tasks)
        for html in htmls:
            print(html[:100])

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())


답변

요청은 현재 지원되지 않으며 asyncio그러한 지원을 제공 할 계획이 없습니다. 사용 방법을 알고 있는 사용자 정의 “전송 어댑터”( 여기 에서 설명 )를 구현할 수 있습니다 asyncio.

시간이 지나면 실제로 들여다 볼 수 있지만 약속 할 수는 없습니다.


답변

Pimin Konstantin Kefaloukos의 기사에 async / await 루프 및 스레딩의 좋은 사례가 있습니다. Python 및 asyncio를 사용한
쉬운 병렬 HTTP 요청 :

총 완료 시간을 최소화하기 위해 요청 수에 맞게 스레드 풀의 크기를 늘릴 수 있습니다. 운 좋게도 다음에서 볼 수 있듯이 쉽게 수행 할 수 있습니다. 아래 코드 목록은 20 개의 작업자 스레드로 구성된 스레드 풀을 사용하여 20 개의 비동기 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())


답변