Асинхронный роут выполняется не совсем асинхронно

Рейтинг: 0Ответов: 1Опубликовано: 11.05.2023

Цель:

Запустить функцию bm() асинхронно для с помощью TaskFactory. Ну и после запуска вычитывать прогресс выполнения.

Проблема:

Код полностью работает. Проблема в асинхронности. Ставлю точку на return в роуте и прохожу его до того как функция bm() закончит выполенние. Но в другом софте (где ожидаю ответ) результат приходит только после выполнения функции bm()

Роут:

@app.route('/api/startMerge', methods= ['POST'])
async def big_merge():
    res = None
    try:
        res = await taskFactory.startTask(request)
        return res
    except Exception as e:
        print(str(e))
        return '', 400

@app.route('/api/getMergeStatus', methods= ['POST'])
def get_merge_status():
    id = request.values['id']
    return taskFactory.getStatus(id)

Менеджер тасков:

class TaskFactory:
    operations = []
    
    def __init__(self) -> None:
        pass
    
    async def startTask(self, request):
        try:
            operation = Operation()
            # asyncio.create_task(bm(request, operation.setStatus))
            asyncio.gather(bm(request, operation.setStatus))
            self.operations.append(operation)
            return {
                'Status': 'success',
                'Value': operation.id
            }
        except Exception as e:
              return {
                'Status': 'error',
                'Value': str(e)
            }
        
    def getStatus(self, id):
        obj = next(filter(lambda x: x.id == id, self.operations), None)
        if obj is not None:
            return {
                'Status': obj.status,
                'Message': obj.message,
                'ProgressValue': obj.progressValue,
                'Object': obj.object
            }
        else:
            return None

Функция:

   async def bm(request, changeStatusFunc = None):
      .....

Ответы

▲ 0

Асинхронные функции работают в том месте где написано await. Если bm делает много легких операций - вставь между операциями await asyncio.sleep(0). Если bm тяжелая, то обязательно выполнение через run_in_executor https://docs.python.org/3/library/asyncio-eventloop.html#executing-code-in-thread-or-process-pools