python-asyncio TypeError: объект dict нельзя использовать в выражении 'await'
Я использую сторонний модуль для извлечения данных из 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
Почему я не могу ждать тип ('dict')? Это можно обойти? Если async/await с asyncio не будет работать со сторонним модулем, который не возвращает сопрограмму, то каковы мои другие варианты?
4 ответа
Только асинхронный (определяется с async def
) функции можно ожидать. Вся идея в том, что такие функции написаны особым образом, что позволяет запускать (await
) их без блокировки событийного цикла.
Если вы хотите получить результат от общего (определяется с помощью def
) функция, которая занимает значительное время, у вас есть эти опции:
- переписать всю эту функцию, чтобы она была асинхронной
- вызвать эту функцию в другом потоке и ожидать результата асинхронно
- вызовите эту функцию в другом процессе и ожидайте результата асинхронно
Обычно вы хотите выбрать второй вариант.
Вот пример того, как это сделать:
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. Я думаю, это вам очень поможет.
Вам не нужно ждать, какая функция работает асинхронно
async def getData():
retrienveData = thirdPartyAPIWrapper.data()
return retrieveData
Как 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
вспомогательная функция в этой библиотеке.
Я пишу тестовые примеры, и мне нужно имитировать асинхронную функциональность. Итак, вы можете написать такую простую вспомогательную функцию.
async def resolve(val):
return val
Теперь можно ждать чего угодно
foo = resolve(1)
await foo # No error!