pythonリクエストライブラリをしばらく使用していましたが、最近リクエストを非同期的に行う必要がありました。つまり、HTTPリクエストを送信し、メインスレッドを実行し、リクエストが返されたときにコールバックを呼び出します。
当然、私はgrequestsライブラリ( https://github.com/kennethreitz/grequests )に導かれましたが、その振る舞いについて混乱しています。例えば:
import grequests
def print_res(res):
from pprint import pprint
pprint (vars(res))
req = grequests.get('http://www.codehenge.net/blog', hooks=dict(response=print_res))
res = grequests.map([req])
for i in range(10):
print i
上記のコードは次の出力を生成します。
<...large HTTP response output...>
0
1
2
3
4
5
6
7
8
9
Grequests.map()呼び出しは、HTTP応答が利用可能になるまで明らかにブロックします。ここで「非同期」の動作を誤解したようです。grequestsライブラリは、複数のHTTP要求を同時に実行し、すべての応答を単一のコールバックに送信するためのものです。これは正確ですか?
grequests
を使用したくない場合は、標準ライブラリのrequests
+ threading
モジュールを使用して、コールバックで要求を実装するだけです。実際には非常に簡単です。コールバックを使用してリクエストを送信するだけの場合、APIはgrequests
で提供されるAPIよりも優れています。
from threading import Thread
from requests import get, post, put, patch, delete, options, head
request_methods = {
'get': get,
'post': post,
'put': put,
'patch': patch,
'delete': delete,
'options': options,
'head': head,
}
def async_request(method, *args, callback=None, timeout=15, **kwargs):
"""Makes request on a different thread, and optionally passes response to a
`callback` function when request returns.
"""
method = request_methods[method.lower()]
if callback:
def callback_with_args(response, *args, **kwargs):
callback(response)
kwargs['hooks'] = {'response': callback_with_args}
kwargs['timeout'] = timeout
thread = Thread(target=method, args=args, kwargs=kwargs)
thread.start()
JSでのAJAX呼び出しのように機能することを確認できます。別のスレッドでリクエストを送信し、メインスレッドで何かを行い、リクエストが返されたらコールバックを呼び出します。応答内容を印刷するだけです。
async_request('get', 'http://httpbin.org/anything', callback=lambda r: print(r.json()))
for i in range(10):
print(i)
リクエストのリストを作成し、_.imap
_で送信します:
_event_list = [grequests.get(url_viol_card, params={"viol": i},
session=session) for i in print_ev_list]
for r in grequests.imap(event_list, size=5):
print(r.request.url)
_
session
はrequests.Session()
オブジェクトです(オプション)size=5
_同時に5つのリクエストを送信します。そのうちの1つが完了するとすぐに、次のリクエストが送信されます