requestsライブラリはPythonでAPIリクエストを扱う際に非常に使いやすく、K氏が開発した非同期処理をサポートしていないため、逐次実行される。テスト効率を向上させるために並列処理が必要な場合、マルチスレッドやコルーチン、gevent、aiohttpなどの技術が利用可能だが、実装がやや複雑である。
grequestsはK氏がgeventとrequestsを組み合わせて開発した並列リクエスト送信ライブラリであり、簡単なインターフェースで利用できる。
インストール方法: pip install gevent grequests
プロジェクトURL: https://github.com/spyoungtech/grequests
grequestsの基本的な使用方法
まず、リクエストタスクのリストを作成し、grequests.map()メソッドを使用して並列処理を行う。
import grequests
request_tasks = [ # リクエストタスクリスト
grequests.get('http://httpbin.org/get?a=1&b=2'),
grequests.post('http://httpbin.org/post', data={'x':1,'y':2}),
grequests.put('http://httpbin.org/post', json={'x': 1, 'y': 2}),
]
response_results = grequests.map(request_tasks) # 並列実行後結果取得
print(response_results[0].text) # 最初のリクエストの応答テキスト出力
grequestsはget、post、put、deleteなどのHTTPメソッドをサポートしており、パラメータの指定方法はrequestsと同様である。
requestsとのパフォーマンス比較
100回のGitHubへのリクエスト処理時間を比較する。
requestsによる逐次処理:
import requests
import time
start = time.time()
responses = [requests.get('https://github.com') for _ in range(100)]
print(time.time()-start)
grequestsによる並列処理:
import grequests
import time
start = time.time()
request_tasks = [grequests.get('https://github.com') for _ in range(100)]
response_results = grequests.map(request_tasks)
print(time.time()-start)
実測ではrequestsは約100秒、grequestsは約3.58秒で処理が完了した。
例外処理の実装
複数リクエスト送信時にURLが存在しない、タイムアウトなどエラーが発生する可能性があるため、カスタム例外処理を設定可能。
import grequests
def handle_exception(request, error):
print("リクエスト失敗")
request_tasks = [
grequests.get('http://httpbin.org/delay/1', timeout=0.001), # タイムアウト
grequests.get('http://invaliddomain/'), # 存在しないドメイン
grequests.get('http://httpbin.org/status/500') # 500エラーを返すリクエスト
]
response_results = grequests.map(request_tasks, exception_handler=handle_exception)
print(response_results)
実行結果:
リクエスト失敗
リクエスト失敗
[None, None, <Response [500]>]