비동기식으로 요청을 사용하려면 어떻게 해야 합니까?
다음에서 병렬 http 요청 작업을 수행합니다.asyncio
하지만 나는 그것을 발견합니다.python-requests
의 이벤트 루프를 차단합니다.asyncio
iohttp를 찾았지만 http 프록시를 사용한 http 요청 서비스를 제공하지 못했습니다.
그래서 저는 비동기식 http 요청을 할 수 있는 방법이 있는지 알고 싶습니다.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를 참조하십시오.
iohttp는 이미 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())
또한 라이브러리가 있는데, 이는 요청에 대한 대체품의 감소입니다.async/await
지지하다.
요청이 현재 지원되지 않습니다.asyncio
그리고 그러한 지원을 제공할 계획은 없습니다.사용 방법을 아는 사용자 지정 "전송 어댑터"(여기서 설명한 바와 같이)를 구현할 수 있습니다.asyncio
.
제가 시간이 좀 있다면, 제가 실제로 조사해 볼 수도 있지만, 저는 아무것도 약속할 수 없습니다.
Pimin Constantin Kefaloukos 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())
iohttp가 완전히 기능하는 웹 프레임워크라는 점을 고려하면, 저는 비동기 요청을 지원하는 http(https://www.python-httpx.org/) 처럼 좀 더 가벼운 것을 사용할 것을 제안합니다.요청과 거의 동일한 api를 가지고 있습니다.
>>> async with httpx.AsyncClient() as client:
... r = await client.get('https://www.example.com/')
...
>>> r
<Response [200 OK]>
공개자:Following code creates different threads for each function.
사용이 더 간단하므로 일부 경우에 유용할 수 있습니다.하지만 그것은 비동기가 아니라 여러 스레드를 사용하여 비동기의 환상을 제공한다는 것을 알아야 합니다. 비록 장식가가 그렇게 제안하더라도 말입니다.
기능을 차단하지 않도록 하려면 데코레이터를 복사하고 콜백 기능을 매개 변수로 사용하여 기능을 장식하기만 하면 됩니다.콜백 기능은 기능에서 반환된 데이터를 수신합니다.
import asyncio
import requests
def run_async(callback):
def inner(func):
def wrapper(*args, **kwargs):
def __exec():
out = func(*args, **kwargs)
callback(out)
return out
return asyncio.get_event_loop().run_in_executor(None, __exec)
return wrapper
return inner
def _callback(*args):
print(args)
# Must provide a callback function, callback func will be executed after the func completes execution !!
@run_async(_callback)
def get(url):
return requests.get(url)
get("https://google.com")
print("Non blocking code ran !!")
언급URL : https://stackoverflow.com/questions/22190403/how-could-i-use-requests-in-asyncio
'programing' 카테고리의 다른 글
판다의 여러 데이터 프레임 열에서 "별도로" 선택하는 방법은 무엇입니까? (0) | 2023.07.11 |
---|---|
스프링 부트 - 대체 시작 클래스를 지정하는 방법(다중 진입점) (0) | 2023.07.11 |
Apache poi를 사용하여 Excel 셀에서 항상 소수점 두 개 표시 (0) | 2023.07.06 |
쿼리를 사용하여 열을 삭제하지 않고 열의 데이터 유형을 변경하는 방법은 무엇입니까? (0) | 2023.07.06 |
UNIX epoch를 Date 개체로 변환 (0) | 2023.07.06 |