回答:
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を参照してください。
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())
Pythonおよびasyncioを使用したPimin Konstantin Kefaloukos Easy parallel 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())
for i in range(10000)
1つのリクエストが失敗したりタイムアウトしたりする可能性があるので、私はできませんか?
subprocess
、コードを並列化するために使用できます。