web-dev-qa-db-ja.com

Pythonリクエストを使用した非同期リクエスト

Pythonの requests library のドキュメント内にあるサンプルを試しました。

async.map(rs)を使用して、応答コードを取得しますが、要求された各ページのコンテンツを取得したいです。たとえば、これは機能しません。

out = async.map(rs)
print out[0].content
118
trbck

注意

以下の答えは、リクエストv0.13.0 +に適用されるnotです。この質問が書かれた後、非同期機能は grequests に移動しました。ただし、以下のrequestsgrequestsに置き換えるだけで機能します。

私はこのリクエストを、v0.13.0未満のリクエストの使用に関する元の質問を反映するためにそのまま残しました。


async.mapasynchronouslyで複数のタスクを実行するには:

  1. 各オブジェクト(タスク)で実行する機能の定義
  2. その関数をリクエストのイベントフックとして追加します
  3. すべてのリクエスト/アクションのリストで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)
133
Jeff

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は、同時リクエスト、つまり複数のリクエストが同じサーバーに送信される場合の制限を設定していないようです。

69
outforawhile

requests-futuresgrequestsの両方をテストしました。 Grequestsは高速ですが、モンキーパッチと依存関係に関する追加の問題をもたらします。 requests-futuresはgrequestsよりも数倍遅いです。独自の単純にラップされたリクエストをThreadPollExecutorに書き込むことにしました。これは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
40
Anton Shelin

多分 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に関与したくない場合は、良いイベントです。

26
Dreampuf

私はこれがしばらく閉じられていることを知っていますが、要求ライブラリに基づいて構築された別の非同期ソリューションを促進することが役立つと思いました。

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/

7
Monkey Boson
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...
5
Jason Pump

私はしばらくの間、githubのGist APIに対する非同期呼び出しにpythonリクエストを使用しています。

例については、次のコードを参照してください。

https://github.com/davidthewatson/flasgist/blob/master/views.py#L60-72

このスタイルのpythonは最も明確な例ではないかもしれませんが、コードが機能することを保証できます。これがあなたを混乱させるかどうか私に知らせてください、そして、私はそれを文書化します。

2
David Watson

Asyncioを使用する場合、requests-asyncrequestsのasync/await機能を提供します- https://github.com/encode/requests-async

1
Tom Christie

また、Pythonの非同期メソッドを使用していくつかのことを試しましたが、非同期プログラミングにツイストを使用した方がはるかに幸運でした。問題が少なく、十分に文書化されています。ここに、あなたが試しているものに似た何かのリンクがあります。

http://pythonquirks.blogspot.com/2011/04/twisted-asynchronous-http-request.html

0
Sam