178

で並列 http 要求タスクを実行したいのですが、それでは のイベント ループがブロックasyncioされることがわかりました。aiohttpを見つけましたが、http プロキシを使用して http リクエストのサービスを提供できませんでした。python-requestsasyncio

を使用して非同期の http 要求を行う方法があるかどうかを知りたいですasyncio

4

7 に答える 7

217

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())

これにより、両方の応答が並行して取得されます。

awaitPython 3.5 では、新しい/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を参照してください。

于 2014-03-14T20:06:16.730 に答える
102

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())
于 2014-05-21T13:30:47.190 に答える
14

Requests は現在サポートasyncioされておらず、そのようなサポートを提供する予定もありません。を使用する方法を知っているカスタム「トランスポート アダプター」 (ここで説明したように) を実装できる可能性がありますasyncio

時間があれば実際に調べてみるかもしれませんが、約束はできません。

于 2014-03-05T10:56:57.310 に答える
2

免責事項:Following code creates different threads for each function.

これは、使用が簡単なため、一部のケースで役立つ場合があります。ただし、非同期ではなく、複数のスレッドを使用して非同期の錯覚を与えることを知っておいてください。

関数をブロックしないようにするには、デコレータをコピーして、コールバック関数をパラメータとして任意の関数をデコレートします。コールバック関数は、関数から返されたデータを受け取ります。

import asyncio
import requests


def run_async(callback):
    def inner(func):
        def wrapper(*args, **kwargs):
            def __exec():
                out = func(*args, **kwargs)
                callback(out)
                return out

            return asyncio.get_event_loop().run_in_executor(None, __exec)

        return wrapper

    return inner


def _callback(*args):
    print(args)


# Must provide a callback function, callback func will be executed after the func completes execution !!
@run_async(_callback)
def get(url):
    return requests.get(url)


get("https://google.com")
print("Non blocking code ran !!")
于 2020-12-28T16:20:53.957 に答える