Как вернуть значение из функции asyn c при выполнении задачи в фоновом режиме? - PullRequest
0 голосов
/ 26 мая 2020

[править] Python 3.6

Есть функция:

def main(request):
    do_something() // task takes some days
    responce = {'status': 'started!'}
    return responce

Мне нужно, чтобы она возвращала ответ сразу после запуска do_something () и НЕ дожидалась do_something () быть законченным. Я уже пробовал это:

def main(request):
    Thread(target=do_something).start()
    responce = {'status': 'started!'}
    return responce

Работает, только если do_something () не содержит внутри потоков. Пожалуйста, помогите с использованием asyn c -wait здесь 'без лишних строк кода'

[update] это отлично работает только в Jupyter, но не в контейнере docker (появляется RuntimeError: There нет текущего события l oop в потоке '):

import asyncio

async def do_something():
    print("internal training started")
    await asyncio.sleep(5)
    print("internal training finished")

def main():
    asyncio.ensure_future(train_models())
    responce = {'status': 'started!'}
    return responce
print(main())

[обновление] проблема была не с потоками и асинхронными функциями, проблема была с azure -функциями. [закрыто]

1 Ответ

0 голосов
/ 26 мая 2020

Использование asyncio:

import asyncio


async def do_something():
    for i in range(10):
        print(f"Been doing expensive stuff for {i} seconds.")
        await asyncio.sleep(1)


def handle_request(request):
    task = asyncio.create_task(do_something())
    response = {request: {"status": "started!"}}
    return response, task


async def main():
    response, task = handle_request("request")
    print(response)
    await task
    print("Program finished.")


if __name__ == "__main__":
    asyncio.run(main())

Вывод:

{'request': {'status': 'started!'}}
Been doing expensive stuff for 0 seconds.
Been doing expensive stuff for 1 seconds.
Been doing expensive stuff for 2 seconds.
Been doing expensive stuff for 3 seconds.
Been doing expensive stuff for 4 seconds.
Been doing expensive stuff for 5 seconds.
Been doing expensive stuff for 6 seconds.
Been doing expensive stuff for 7 seconds.
Been doing expensive stuff for 8 seconds.
Been doing expensive stuff for 9 seconds.
Program finished.

Или альтернативно threading:

import time
from threading import Thread


def do_something():
    for i in range(10):
        print(f"Been doing expensive stuff for {i} seconds.")
        time.sleep(1)


def handle_request(request):
    thread = Thread(target=do_something)
    thread.start()
    response = {request: {"status": "started!"}}
    return response, thread


def main():
    response, thread = handle_request("request")
    print(response)
    thread.join()
    print("Program finished.")


if __name__ == "__main__":
    main()

Вывод:

Been doing expensive stuff for 0 seconds.
{'request': {'status': 'started!'}}
Been doing expensive stuff for 1 seconds.
Been doing expensive stuff for 2 seconds.
Been doing expensive stuff for 3 seconds.
Been doing expensive stuff for 4 seconds.
Been doing expensive stuff for 5 seconds.
Been doing expensive stuff for 6 seconds.
Been doing expensive stuff for 7 seconds.
Been doing expensive stuff for 8 seconds.
Been doing expensive stuff for 9 seconds.
Program finished.
...