Pythonのリクエストライブラリのドキュメントに含まれているサンプルを試しました。
ではasync.map(rs)
、応答コードを取得していますが、要求された各ページのコンテンツを取得したいと考えています。たとえば、これは機能しません。
out = async.map(rs)
print out[0].content
requests-threads
現在存在しているようです。
Pythonのリクエストライブラリのドキュメントに含まれているサンプルを試しました。
ではasync.map(rs)
、応答コードを取得していますが、要求された各ページのコンテンツを取得したいと考えています。たとえば、これは機能しません。
out = async.map(rs)
print out[0].content
requests-threads
現在存在しているようです。
回答:
以下の回答は、v0.13.0以降のリクエストには適用されません。この質問が書かれた後、非同期機能はgrequestsに移動しました。しかし、あなただけ置き換えることができrequests
てgrequests
、以下の、それが動作するはずです。
v0.13.0未満のリクエストの使用に関する元の質問を反映するために、この回答はそのままにしておきます。
async.map
非同期で複数のタスクを実行するには、以下を行う必要があります。
async.map
すべてのリクエスト/アクションのリストを呼び出す例:
from requests import async
# If using requests > v0.13.0, use
# from grequests import async
urls = [
'http://python-requests.org',
'http://httpbin.org',
'http://python-guide.org',
'http://kennethreitz.com'
]
# A simple task to do to each response object
def do_something(response):
print response.url
# A list to hold our things to do via async
async_list = []
for u in urls:
# The "hooks = {..." part is where you define what you want to do
#
# Note the lack of parentheses following do_something, this is
# because the response will be used as the first argument automatically
action_item = async.get(u, hooks = {'response' : do_something})
# Add the task to our list of things to do via async
async_list.append(action_item)
# Do our list of things to do via async
async.map(async_list)
from grequests import async
動作しません..そしてこの何かの定義が私にとってはうまくいきますdef do_something(response, **kwargs):
、私はstackoverflow.com/questions/15594015/…
from requests import async
によってimport grequests as async
私のために働きました。
async
は現在、独立したモジュールですgrequests
。
ここを参照してください:https://github.com/kennethreitz/grequests
そしてそこに:Python経由で複数のHTTPリクエストを送信するための理想的な方法は?
$ pip install grequests
スタックを構築します。
import grequests
urls = [
'http://www.heroku.com',
'http://tablib.org',
'http://httpbin.org',
'http://python-requests.org',
'http://kennethreitz.com'
]
rs = (grequests.get(u) for u in urls)
スタックを送る
grequests.map(rs)
結果は次のようになります
[<Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>]
grequestsは同時リクエスト、つまり複数のリクエストが同じサーバーに送信される場合の制限を設定していないようです。
results = grequests.map(rs)
、コードをこの行がブロックされた後、私は非同期効果を見ることができますか?
requests-futuresとgrequestsの両方をテストしました。Grequestsはより高速ですが、サルのパッチと依存関係に関する追加の問題をもたらします。requests-futuresはgrequestsより数倍遅いです。私は独自のリクエストをThreadPoolExecutorに単純にラップすることを決定し、grequestsとほぼ同じ速さでしたが、外部の依存関係はありませんでした。
import requests
import concurrent.futures
def get_urls():
return ["url1","url2"]
def load_url(url, timeout):
return requests.get(url, timeout = timeout)
with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
future_to_url = {executor.submit(load_url, url, 10): url for url in get_urls()}
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future]
try:
data = future.result()
except Exception as exc:
resp_err = resp_err + 1
else:
resp_ok = resp_ok + 1
多分requests-futuresは別の選択肢です。
from requests_futures.sessions import FuturesSession
session = FuturesSession()
# first request is started in background
future_one = session.get('http://httpbin.org/get')
# second requests is started immediately
future_two = session.get('http://httpbin.org/get?foo=bar')
# wait for the first request to complete, if it hasn't already
response_one = future_one.result()
print('response one status: {0}'.format(response_one.status_code))
print(response_one.content)
# wait for the second request to complete, if it hasn't already
response_two = future_two.result()
print('response two status: {0}'.format(response_two.status_code))
print(response_two.content)
オフィス文書にもオススメです。geventを使用したくない場合は、それが適切です。
ThreadPoolExecutor(max_workers=10)
私は投稿された回答のほとんどに多くの問題があります-それらは制限された機能で移植された非推奨のライブラリを使用するか、またはリクエストの実行にあまりにも多くの魔法のあるソリューションを提供し、エラー処理を困難にします。上記のカテゴリのいずれにも該当しない場合は、サードパーティのライブラリであるか、廃止されています。
一部のソリューションは純粋にhttpリクエストで問題なく機能しますが、ソリューションは他の種類のリクエストには不十分です。ここでは高度にカスタマイズされたソリューションは必要ありません。
Python組み込みライブラリを使用するだけでasyncio
、あらゆるタイプの非同期リクエストを実行できるだけでなく、複雑でユースケース固有のエラー処理に十分な流動性を提供できます。
import asyncio
loop = asyncio.get_event_loop()
def do_thing(params):
async def get_rpc_info_and_do_chores(id):
# do things
response = perform_grpc_call(id)
do_chores(response)
async def get_httpapi_info_and_do_chores(id):
# do things
response = requests.get(URL)
do_chores(response)
async_tasks = []
for element in list(params.list_of_things):
async_tasks.append(loop.create_task(get_chan_info_and_do_chores(id)))
async_tasks.append(loop.create_task(get_httpapi_info_and_do_chores(ch_id)))
loop.run_until_complete(asyncio.gather(*async_tasks))
仕組みは簡単です。非同期で発生させたい一連のタスクを作成し、それらのタスクを実行して完了時に終了するようループに要求しています。メンテナンスが不足したり、必要な機能が不足したりすることのない追加のライブラリはありません。
async
ます。次に、たとえば、行うことができます await response = requests.get(URL)
。番号?
requests
、URLのリストを同期的に呼び出すよりも、ラッパーを作成する方がやや高速(場合によっては低速)であることがわかりました。たとえば、上記の戦略を使用して10回応答するために3秒かかるエンドポイントを要求すると、約30秒かかります。真のasync
パフォーマンスが必要な場合は、などを使用する必要がありますaiohttp
。
私はこれがしばらくクローズされていることを知っていますが、要求ライブラリに基づいて構築された別の非同期ソリューションを促進することは有用であると思いました。
list_of_requests = ['http://moop.com', 'http://doop.com', ...]
from simple_requests import Requests
for response in Requests().swarm(list_of_requests):
print response.content
ドキュメントはこちらです:http : //pythonhosted.org/simple-requests/
threads=list()
for requestURI in requests:
t = Thread(target=self.openURL, args=(requestURI,))
t.start()
threads.append(t)
for thread in threads:
thread.join()
...
def openURL(self, requestURI):
o = urllib2.urlopen(requestURI, timeout = 600)
o...
あなたがasyncio使用したい場合は、その後requests-async
のための非同期/のawait機能を提供しますrequests
- https://github.com/encode/requests-async
私はしばらくの間、githubのgist APIに対する非同期呼び出しにpythonリクエストを使用しています。
例については、こちらのコードをご覧ください。
https://github.com/davidthewatson/flasgist/blob/master/views.py#L60-72
このスタイルのpythonは明確な例ではないかもしれませんが、コードが機能することを保証できます。これがあなたを混乱させるかどうか教えてください、私はそれを文書化します。
httpx
そのために使用できます。
import httpx
async def get_async(url):
async with httpx.AsyncClient() as client:
return await client.get(url)
urls = ["http://google.com", "http://wikipedia.org"]
# Note that you need an async context to use `await`.
await asyncio.gather(*map(get_async, urls))
関数構文が必要な場合、gamla libはこれをにラップしget_async
ます。
その後、行うことができます
await gamla.map(gamla.get_async(10), ["http://google.com", "http://wikipedia.org"])
これ10
は秒単位のタイムアウトです。
(免責事項:私はその著者です)
また、Pythonの非同期メソッドを使用していくつかのことを試しましたが、非同期プログラミングにツイストを使用した方がずっとうまくいきました。問題が少なく、十分に文書化されています。これは、あなたがねじれで試みているものに類似した何かのリンクです。
http://pythonquirks.blogspot.com/2011/04/twisted-asynchronous-http-request.html