LINUX.ORG.RU

FastAPI и запуск подпроцесса в python

 ,


0

1

Здравствуйте.

Хочу написать что-то по типу такого:

def runandget():
    myprocess = subprocess.run(["node", "./js/duck.js"], stdout=subprocess.PIPE)
    thoutput = myprocess.stdout.decode('utf-8')
    return thoutput

@app.post("/doit")
def dothis():
    resultfunc = runandget()
    return {"result": resultfunc}

Но функция runandget() выходит мгновенно и переменная resultfunc остаётся пустой.

При запуске же этой функции отдельно от FastAPI, всё выполняется как и должно.

Как попросить FastAPI подождать, пока процесс завершится и получить его результат?

Во первых, в смысле выходит мгновенно? У тебя полностью синхронный код. Если у тебя пустая строка в resultfunc, это значит, что myprocess.stdout.decode('utf-8') действительно возвращает пустую строку. Добавь логов и посмотри, что там творится.

То, что ты делаешь это оооочень плохой паттерн. Делай запуск процесса асинхронной задачей.

Aswed ★★★★★
()
Ответ на: комментарий от slovazap

Run the command described by args. Wait for command to complete, then return a CompletedProcess instance.

Т.е. subrocess.run() ждёт, пока процесс полностью закончит работу и только потом выходит

Architector
() автор топика
Ответ на: комментарий от Aswed

А разве то, что у меня функция dothis() не async - это будет блокировать приём других запросов к API? Или производительность будет меньше?

А по вопросу дело в том, что если запустить:

subprocess.run("print.sh", stdout=subprocess.PIPE)

И файл print.sh:

#!/bin/bash

echo 'I work'

То всё равно возвращается пустая строка

Architector
() автор топика
Ответ на: комментарий от Architector

А разве то, что у меня функция dothis() не async - это будет блокировать приём других запросов к API?

Конечно. Порождать процесс на каждый запрос это очень дорого.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Arrrgh, у меня ошибка была в коде js, ужас.

Точнее то, что там я не дожидался завершения асинхронных функций, потому процесс и возвращал ничего.

Но вот теперь другая проблема. Поскольку в js и python асинхронность примерно одинаковая, вот пример:

Есть библиотека, которая работает только асинхронно и больше никак. И нужно в синхронном коде дождаться выполнения её работы здесь и сейчас, иначе её результат влияет на дальнейшие действия.

Так вот в лоб написать await нельзя, ибо всё происходит в обычной функции, а дождаться надо. Как?

Может есть какой-то метод это всё через event’ы сделать, либо ещё как, иначе как же тогда FastAPI определяет завершение работы асинхронных функций и отправляет ответ, когда функция завершила свою работу и выдаёт результат.

А за ‘async’ функции под декоратором спасибо, учту. Я просто думал FastAPI у себя под капотом пул потоков держит, поэтому не видел смысла в использовании ‘async’ функций.

Эх, как же сложно в этих притонах и js’ах, вот в c++…. всё как-то проще с этим - ничего нет, всё сам под себя делаешь

Architector
() автор топика
Ответ на: комментарий от Architector

Есть библиотека, которая работает только асинхронно и больше никак. И нужно в синхронном коде дождаться выполнения её работы здесь и сейчас, иначе её результат влияет на дальнейшие действия.

https://docs.python.org/3/library/asyncio-task.html#running-an-asyncio-program

Сама проблема звучит вразрез с ником, менять надо архитектуру приложения. Разбить на части, пусть асинхронный код крутится отдельно.

vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от Architector

Так вот в лоб написать await нельзя, ибо всё происходит в обычной функции, а дождаться надо. Как?

Запустить событийный цикл и «в лоб написать await». asyncio.run

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)

советую тебе это выполнять асинхронно, тем более ты выбрал фреймворк который это решает из коробки

noname_user ★★★
()
Ответ на: комментарий от Architector

А разве то, что у меня функция dothis() не async - это будет блокировать приём других запросов к API?

Естессно. Но даже если ты сделаешь ее async, то все равно будет. Потому что subprocess.run это не async операция. У тебя сервер повиснет пока subprocess.run не выполнится. Сомневаюсь, что у тебя там запуск скипта echo "hello world" наверняка что-то посложнее.

То всё равно возвращается пустая строка

Читай мануалы https://docs.python.org/3/library/subprocess.html

Во-первых тебе нужен check_output, а не run. Во вторых у них обоих такой синтаксис, что тебе надо делать запуск башевого скрипта типа check_output(["/bin/bash", "script.sh"])

Aswed ★★★★★
()
Ответ на: комментарий от Aswed

сервер так-то не повиснет, так как там не один тред, а вот тред - да. там нужно либо по хттп дергать нодовский демон либо через шину с ним общаться

tz4678 ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.