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!
Другие вопросы по тегам