Запуск неблокирующего вызова асинхронной функции через HTTP-запросы к маршруту в приложении Python 3.6 Flask - PullRequest
0 голосов
/ 26 мая 2018

В настоящее время я пишу небольшой микросервис на основе колб, который запускает другие скрипты python через вызовы CLI с использованием модуля subprocess python.Моя конечная цель - сделать неблокирующий вызов асинхронной функции, инициируемый http-запросами к маршруту в службе, и получить от службы ответ 200 от маршрута, пока асинхронная функция выполняется в фоновом режиме.

Iпросматривал документы (я использую Python 3.6.3 для этого сервиса) не могу понять, как этого добиться.Вот небольшой пример того, как структурирован мой код:

@app.route('/execute_job')
def execute_job():
    params = ...
    run_async_job(params)
    return 'Launched async job according to params, it is now running.'

async def run_async_job(params):
    command = 'run_python_cli_scripts args'
    proc = subprocess.Popen(command)
    # change some envs, do some file io, yada yada yada
    ...
    while True:
        if proc.poll() is not None: # the cli script is finished
            return notify_external_api_job_complete()

Я знаю, что простой вызов run_async_job(params) на самом деле не начинает его выполнение, а вместо этого возвращает awaitable или Task, который должен бытьброшенный в event_loop.Моя проблема в том, что я не могу понять, как выполнить эту задачу в event_loop так, чтобы return в execute_ job был достигнут до ее завершения.Это возможно?Это мое первое знакомство с асинхронным питоном, и я ищу поведение, похожее на то, что вы увидите в асинхронном JavaScript.Пытается использовать async def для функции, которую я хочу, чтобы неблокирует неправильный подход, или есть способ запустить задачи в event_loop неблокирующим образом, чтобы можно было достичь вышеупомянутого return 'Launched async job according to params, it is now running.'и функция завершена до run_async_job(params) завершена?

Заранее спасибо за ваше время и мудрость.

1 Ответ

0 голосов
/ 29 мая 2018

От потомков: я выбрал дочерний процесс, запущенный через модуль subprocess.Это было достигнуто путем преобразования файла библиотеки, из которого я импортировал мою функцию async def 'd, в скрипт, который использует аргументы командной строки, проанализированные из модуля argparse.Мой маршрут теперь выглядит как

@app.route('/execute_job')
def execute_job():
    params = ...
    command = ('python', params)
    subprocess.Popen(command)
    return 'Launched async job according to params, it is now running.'

edit: formatting

...