aiohttp を使用して、TCP要求を別のサーバーに送信するAPIサーバーを構築します。 TCPリクエストは同期であり、私の目的のためのブラックボックスです。したがって、私のリクエストはこれらのリクエストがAPI全体をブロックしていることです。モジュールリクエストを非同期コルーチンでラップする方法が必要です。 APIの残りをブロックしません。
そのため、単純な例としてsleep
を使用するだけで、時間のかかる同期コードを何らかの方法で非ブロッキングコルーチンにラップする方法はありますか。
async def sleep_async(delay):
# After calling sleep, loop should be released until sleep is done
yield sleep(delay)
return 'I slept asynchronously'
最終的に、私は このスレッド で答えを見つけました。私が探していた方法は run_in_executor です。これにより、イベントループをブロックすることなく、同期関数を非同期で実行できます。
上記のsleep
の例では、次のようになります。
import asyncio
from time import sleep
from concurrent.futures import ProcessPoolExecutor
async def sleep_async(loop, delay):
# Can set executor to None if a default has been set for loop
await loop.run_in_executor(ProcessPoolExecutor(), sleep, delay)
return 'I slept asynchronously'
次の回答も参照してください-> コルーチンが期待される通常の関数をどのように呼び出すのですか?
デコレータを使用して、同期バージョンを非同期バージョンにラップできます。
import time
from functools import wraps, partial
def wrap(func):
@wraps(func)
async def run(*args, loop=None, executor=None, **kwargs):
if loop is None:
loop = asyncio.get_event_loop()
pfunc = partial(func, *args, **kwargs)
return await loop.run_in_executor(executor, pfunc)
return run
@wrap
def sleep_async(delay):
time.sleep(delay)
return 'I slept asynchronously'
またはaioify
libを使用します
% pip install aioify
それから
@aioify
def sleep_async(delay):
pass
遅すぎるかどうかはわかりませんが、デコレータを使用してスレッドで関数を実行することもできます。ただし、co-opブロッキングであるasyncとは異なり、まだco-opブロッキングではないことに注意してください。
def wrap(func):
from concurrent.futures import ThreadPoolExecutor
pool=ThreadPoolExecutor()
@wraps(func)
async def run(*args, loop=None, executor=None, **kwargs):
if loop is None:
loop = asyncio.get_event_loop()
future=pool.submit(func, *args, **kwargs)
return asyncio.wrap_future(future)
return run