Как устранить проблему с rq worker при использовании Flask/Quart?

В структуре вашего проекта: <br/> <pre><code>Project
/app
--__init__.py
--/telegram
----__init__.py
----/bot1
------__init__.py
------testing.py</code></pre> <br/> у вас есть функция test() в модуле main.py, представленная следующим образом: <br/> <pre><code class="python">async def test():
    print('Test message')</code></pre> <br/> Все файлы __init__.py пустые. <br/> <br/> Также в директории Project запущен rq worker. <br/> <br/> При поступлении задания в worker, он успешно выполняет функцию test(), но если в файле app/__init__.py импортировать Quart или Flask, то возникает следующая ошибка: <br/> <pre><code>16:37:44 [Job b3ceac1e-9749-4d0c-965b-a04a7b16c999]: exception raised while executing (app.telegram.bot1.main.test)
Traceback (most recent call last):
  File "/home/likekey/.local/lib/python3.10/site-packages/rq/utils.py", line 107, in import_attribute
    return __builtins__[name]  # type: ignore[index]
KeyError: 'app.telegram.bot1.main.test'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/likekey/.local/lib/python3.10/site-packages/rq/worker.py", line 1633, in perform_job
    return_value = job.perform()
  File "/home/likekey/.local/lib/python3.10/site-packages/rq/job.py, line 1331, in perform
    self._result = self._execute()
  File "/home/likekey/.local/lib/python3.10/site-packages/rq/job.py, line 1365, in _execute
    result = self.func(*self.args, **self.kwargs)
  File "/home/likekey/.local/lib/python3.10/site-packages/rq/job.py, line 499, in func
    return import_attribute(self.func_name)
  File "/home/likekey/.local/lib/python3.10/site-packages/rq/utils.py, line 109, in import_attribute
    raise ValueError('Invalid attribute name: %s' % name)
  • 3 марта 2025 г. 6:44
Ответы на вопрос 1
Ошибка, с которой вы столкнулись, связана с импортом асинхронных функций и использованием Flask или Quart в проекте, который также использует RQ (Redis Queue) для обработки фоновых задач.

Ваша функция `test` является асинхронной функцией, но самой библиотекой RQ не поддерживается выполнение асинхронных функций. Чтобы решить эту проблему, вам нужно выполнить асинхронную функцию в синхронном контексте.

Вот несколько способов, как это можно сделать:

### Способ 1: Использование `asyncio.run()`
Один из решений заключается в обертывании вашей асинхронной функции в синхронную функцию, которая будет вызывать её через `asyncio.run()`:

```python
import asyncio

async def test():
    print('Test message')

def test_sync():
    asyncio.run(test())
```

Теперь вы можете вызывать `test_sync()` в вашем коде, и RQ сможет его выполнить без проблем. Не забудьте изменить задачу, которую добавляете в RQ, на `test_sync`.

### Способ 2: Использование библиотеки `aiohttp`
Если у вас есть необходимость в асинхронном контексте, вы можете использовать библиотеку `aiohttp` для обработки асинхронных вызовов. Пример:

```python
from aiohttp import web

async def test():
    print('Test message')

def test_sync():
    loop = asyncio.get_event_loop()
    loop.run_until_complete(test())
```

### Способ 3: Переход на синхронные функции
Если вы не нуждаетесь во всех возможностях асинхронного программирования в этой функции, вы можете просто переписать её как синхронную:

```python
def test():
    print('Test message')
```

### Примечание по поводу Flask и Quart
Если ваш проект использует Flask или Quart, и в нём требуется асинхронная обработка, вы можете использовать подход с `asyncio.run()`, чтобы вызывать асинхронные функции. Но для RQ вам нужно будет поддерживать синхронный интерфейс для фоновых задач.

### Заключение
В RQ фоновые задачи должны быть синхронными, поэтому вам нужно обернуть свои асинхронные функции в синхронные. Это позволит избежать ошибок, связанных с отсутствием поддержки асинхронных вызовов в RQ, и без проблем интегрировать с Flask или Quart.
Похожие вопросы