Python3.8 asyncio: RuntimeWarning: сопрограмма никогда не ожидалась

Я новичок в асинхронных функциях и пытаюсь сделать несколько вызовов из внешнего API. Concurrent.Futures недостаточно для получения ответов, поэтому я попытался использовать asyncio и httpx, но процесс выдает неизвестную ошибку, которую мне сложно отлаживать.

Кажется, что сопрограмма имеет пустое значение или никогда не вызывается.

Это мой клиент

async def get_product_by_id_async(self, product_id: str) -> Response:
        if product_id is None:
            return None
        response_await = await self.async_client.get(
            url=f"{self.base_url}/api/catalog/stock{product_id}",
            headers=self.headers,
        )

        if response_await.status_code == 200:
            response = json.loads(response_await.text)
            return response

И это моя координирующая функция


async def async_get_products(data_parser):
    path = data_parser.options["path"]
    sku_list = client.run()
    products_list = []
    tasks = [await client.get_product_by_id(sku) for sku in sku_list]
    breakpoint()
    completed = await asyncio.gather(*tasks)
    for product in completed:
        products_list = build_product_df(products_list, product)
    products_df = pd.DataFrame(products_list)
    products_df.to_csv(path, index=False)
    return products_df

def products_processor_concurrent(data_parser):
    return async_get_products(data_parser)

После данного решения в коде появилась новая ошибка: Это след:

Traceback (most recent call last):
  File "manage.py", line 32, in <module>
    module.run()
  File "/opt/project/providers/api/data_collector.py", line 90, in run
    integrator.run()
  File "/opt/project/common/integrator.py", line 448, in run
    self.start_processing()
  File "/opt/project/providers/api/data_collector.py", line 81, in start_processing
    products.run()
  File "/opt/project/common/data_parser.py", line 94, in run
    self.build_dataframe()
  File "/opt/project/common/data_parser.py", line 54, in build_dataframe
    df = func(self)
  File "/opt/project/providers/data_collector.py", line 68, in products_processor_concurrent
    return run(async_get_products(data_parser))
  File "/usr/local/lib/python3.8/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/opt/project/providers/api/data_collector.py", line 57, in async_get_products
    tasks = [await client.get_product_by_id(sku) for sku in sku_list]
  File "/opt/project/providers/api/data_collector.py", line 57, in <listcomp>
    tasks = [await client.get_product_by_id(sku) for sku in sku_list]
TypeError: object dict can't be used in 'await' expression

Я могу понять, почему выдается ошибка, но я не уверен, какой синтаксис будет для ее исправления. Для каждого sku в sku_list вы используете sku в качестве параметра в вашем методе get_product_by_id_async, который возвращает словарь. Похоже, что программа выполняет функцию, не нуждаясь в await перед ней, потому что она запускает функцию, получает словарь, а затем пытается дождаться результата функции вместо ожидания самой функции. Я бы рекомендовал удалить await: tasks = [client.get_product_by_id(sku) for sku in sku_list].

lwashington27 19.11.2022 01:34

@lwashington27 lwashington27 К вашему сведению, программы ждут ожидаемых объектов, а не функций. Выражение вроде await f(x), где f(x) — сопрограмма, фактически ожидает значения, ВОЗВРАЩЕННОГО вызовом функции. Сопрограмма при вызове возвращает объект сопрограммы, который является ожидаемым. В этом смысле сопрограммы похожи на генераторы: вызов генератора возвращает итератор генератора, который возвращает последовательность значений. Сопрограмма выполняет свое тело при ожидании, взаимодействуя с текущим циклом событий при каждом выражении ожидания. Его возвращаемое значение становится значением выражения ожидания.

Paul Cornelius 19.11.2022 10:48
Мутабельность и переработка объектов в Python
Мутабельность и переработка объектов в Python
Объекты являются основной конструкцией любого языка ООП, и каждый язык определяет свой собственный синтаксис для их создания, обновления и...
Другой маршрут в Flask Python
Другой маршрут в Flask Python
Flask - это фреймворк, который поддерживает веб-приложения. В этой статье я покажу, как мы можем использовать @app .route в flask, чтобы иметь другую...
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
Проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
Python PyPDF2 - запись метаданных PDF
Python PyPDF2 - запись метаданных PDF
Python скрипт, который будет записывать метаданные в PDF файл, для этого мы будем использовать PDF ридер из библиотеки PyPDF2 . PyPDF2 - это...
Переменные, типы данных и операторы в Python
Переменные, типы данных и операторы в Python
В Python переменные используются как место для хранения значений. Пример переменной формы:
Почему Python - идеальный выбор для проекта AI и ML
Почему Python - идеальный выбор для проекта AI и ML
Блог, которым поделился Harikrishna Kundariya в нашем сообществе Developer Nation Community.
0
2
186
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы хотите запускать асинхронные функции из синхронных функций, вы должны использовать библиотеку asyncio для их запуска. Ваша последняя функция должна выглядеть так.

def products_processor_concurrent(data_parser):
    from asyncio import run
    return run(async_get_products(data_parser))

Отлично. Он обходит ошибку, но теперь показывает новую. Не хочу вас беспокоить, но на самом деле это действительно новое для меня. TypeError: object dict нельзя использовать в выражении «ожидание». Я редактирую вопрос, чтобы добавить трассировку

bittrago 18.11.2022 19:26

Другие вопросы по теме