Быстрый запуск внешней программы без зависания сервера-api

#python #asynchronous #server #fastapi

#python #асинхронный #сервер #fastapi

Вопрос:

Я пытаюсь запустить сервер Fast-Api на python, который обрабатывает процесс, который занимает около 30-40 секунд для завершения. Второй скрипт использует модуль Selenium для сбора обрабатываемых изображений, поэтому я не думаю, что его можно обработать с помощью обычной асинхронной операции. Я хочу, чтобы этот второй скрипт функционировал как своего рода фоновый рабочий, который не останавливает выполнение других запросов.

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

пример моего кода: приложение FastApi:

 
from fastapi import FastAPI
import sys
import subprocess
app = FastAPI()

def run_program():
    s2_out = s2_out = subprocess.check_output([sys.executable, "script2.py"])
    return s2_out

@app.get("/")
async def read_root():
    return run_program()
  

script2.py Код (из чего сервер получает выходные данные):

 import sys,time,random
counter = 0

def main():
    global counter
    timeValue = random.randint(0,10)
    time.sleep(timeValue)
    print(f'Run Number:{counter} | Finished after:{timeValue} Seconds')
    counter  = 1

if __name__ == "__main__":
    main()
  

ServerTest.py Код (с помощью которого я тестирую сервер.)

 from concurrent.futures import ThreadPoolExecutor
import requests
Counter = 0
def main():
    global Counter
    PreviousNum = Counter
    print(f'Sending Request Number:{PreviousNum}')
    r = requests.get('http://127.0.0.1:8000')
    print(f'Request Number:{PreviousNum} Finished With Response:{r.content.decode()}')
with ThreadPoolExecutor() as executor:
    for x in range(10):
        executor.submit(main)
        Counter  = 1
  

ServerTest.py возвращает

 Sending Request Number:0
Sending Request Number:1
Sending Request Number:2
Sending Request Number:3
Sending Request Number:4
Sending Request Number:5
Sending Request Number:6
Sending Request Number:7
Sending Request Number:8
Sending Request Number:9
Request Number:3 Finished With Response:"Run Number:0 | Finished after:10 Secondsrn"
Request Number:6 Finished With Response:"Run Number:0 | Finished after:10 Secondsrn"
Request Number:2 Finished With Response:"Run Number:0 | Finished after:0 Secondsrn"
Request Number:5 Finished With Response:"Run Number:0 | Finished after:10 Secondsrn"
Request Number:9 Finished With Response:"Run Number:0 | Finished after:6 Secondsrn"
Request Number:4 Finished With Response:"Run Number:0 | Finished after:5 Secondsrn"
Request Number:7 Finished With Response:"Run Number:0 | Finished after:8 Secondsrn"
Request Number:8 Finished With Response:"Run Number:0 | Finished after:1 Secondsrn"
Request Number:0 Finished With Response:"Run Number:0 | Finished after:2 Secondsrn"
Request Number:1 Finished With Response:"Run Number:0 | Finished after:5 Secondsrn"
  

Я знаю, что номер запуска отключен. Это то, что я должен был передать в качестве аргумента вместо того, чтобы помещать внутрь скрипта. Но все элементы пошли 1 на 1. Это приводит к тому, что это занимает 67 секунд.

Идеальный способ и способ, который я ищу для запуска этого сервера, — это общее время, занимающее около 10-11 секунд. Поскольку 10 секунд было самым высоким значением ожидания.

Есть ли способ запустить сервер script2.py через подпроцесс в новом потоке и возвращать каждое значение по мере их завершения вместо ожидания 1 на 1?.

Я не думаю, что подпроцесс поддерживает использование возвращаемых значений через асинхронность.

Приветствуется любая помощь. Спасибо

Редактировать: помимо использования подпроцесса, я также попытался запустить скрипт, импортировав его в серверный скрипт и запустив его через исполнителя пула потоков. Но возврат результата из этого все равно приводит к тому, что он увеличивается 1 на 1.

Комментарии:

1. В какой операционной системе? В Linux есть popen(3) и batch(1) . И popen связан с Python в подпроцессе модуля

2. @BasileStarynkevitch идеально подходит для Windows. является ли popen неблокирующим?

3. Я не знаю Windows. Прочитайте его документацию . В Linux есть poll(2) и многие другие системные вызовы (2) , документацию по которым вы можете прочитать. Большинство системных вызовов Linux связаны с Python, и при необходимости вы можете расширить Python . Прочитайте также расширенное программирование Linux или эквивалентную документацию для Windows