サードパーティのモジュールを使用して、APIからデータを取得しています。私は単にモジュールが非同期でデータを返すのを待ちたいと思いますが、それは時々数秒かかり、アプリをフリーズさせます。ただし、そのモジュールの呼び出しを待機しようとすると、TypeErrorが表示されます。
TypeError: object dict can't be used in 'await' expression
import thirdPartyAPIwrapper
async def getData():
retrienveData = await thirdPartyAPIWrapper.data()
return await retrieveData
def main():
loop = asncio.get_event_loop()
data = loop.run_until_complete(getData())
loop.close
return data
なぜtype( 'dict')を待てないのですか?これを回避する方法はありますか? asyncioを使用したasync/awaitがコルーチンを返さないサードパーティモジュールで動作しない場合、他のオプションは何ですか?
非同期(async def
で定義)関数のみが待機できます。全体的な考えは、そのような関数は、イベントループをブロックせずに実行(await
)できるようにする特別な方法で記述されるということです。
実行にかなりの時間を要する一般的な(def
で定義された)関数から結果を取得する場合、次のオプションがあります。
通常、2番目のオプションを選択します。
これを行う方法の例を次に示します。
import asyncio
import time
from concurrent.futures import ThreadPoolExecutor
_executor = ThreadPoolExecutor(1)
def sync_blocking():
time.sleep(2)
async def hello_world():
# run blocking function in another thread,
# and wait for it's result:
await loop.run_in_executor(_executor, sync_blocking)
loop = asyncio.get_event_loop()
loop.run_until_complete(hello_world())
loop.close()
Asyncioの仕組みについて この回答 をお読みください。私はそれが大いに役立つと思います。
thirdPartyAPIWrapper.data()
は通常の同期関数なので、別のスレッドで呼び出す必要があります。
asgiref
ライブラリにはそのためのヘルパー関数があります。
引数付きのブロッキング関数があると仮定します。
import asyncio
import time
from asgiref.sync import sync_to_async
def blocking_function(seconds: int) -> str:
time.sleep(seconds)
return f"Finished in {seconds} seconds"
async def main():
seconds_to_sleep = 5
function_message = await sync_to_async(blocking_function)(seconds_to_sleep)
print(function_message)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
そのライブラリにはasync_to_sync
ヘルパー関数もあります。